summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsiddharth <s@ricketyspace.net>2021-09-19 13:51:43 -0400
committersiddharth <s@ricketyspace.net>2021-09-19 13:51:43 -0400
commit224ec16b4d9492651f0ae3bb6e4135c022e79705 (patch)
treea0cddab4695fc63b6871e0375feec874c301a8be
parent5a7ec9ac19e258b941e7e86b912b87e46d67335f (diff)
challenge: do challenge 27
-rw-r--r--challenge/c27.go87
-rw-r--r--cryptopals.go2
2 files changed, 89 insertions, 0 deletions
diff --git a/challenge/c27.go b/challenge/c27.go
new file mode 100644
index 0000000..7b5554e
--- /dev/null
+++ b/challenge/c27.go
@@ -0,0 +1,87 @@
+// Copyright © 2021 rsiddharth <s@ricketyspace.net>
+// SPDX-License-Identifier: ISC
+
+package challenge
+
+import (
+ "fmt"
+
+ "ricketyspace.net/cryptopals/lib"
+)
+
+func C27() {
+ // Generate random key.
+ key, err := lib.RandomBytes(16)
+ if err != nil {
+ fmt.Printf("Error: %v", err)
+ return
+ }
+
+ // Make IV same as `key`.
+ iv := key
+
+ // Encrypt `plain` with AES-CBC
+ encrypt := func(plain []byte) []byte {
+ return lib.AESEncryptCBC(plain, key, iv)
+ }
+
+ // Same as lib.AESDecryptCBC but ignores padding error and
+ // checks if plain text has high ASCII values.
+ //
+ // Always returns full plain text; even when there is an
+ // error.
+ decrypt := func(cipher []byte) ([]byte, error) {
+ iter := len(cipher) / 16
+
+ lc := iv
+ output := make([]byte, 0)
+ for i := 0; i < iter; i++ {
+ s := (i * 16)
+ e := (i * 16) + 16
+ c := cipher[s:e]
+ output = append(output, lib.FixedXORBytes(
+ lib.AESInvCipher(c, key), lc)...)
+
+ lc = c
+ }
+
+ // Undo padding
+ plain, err := lib.Pkcs7PaddingUndo(output)
+ if err != nil {
+ // If padding undo fails, just use `output`.
+ plain = output
+ }
+
+ // Check if `plain` high ASCII
+ for _, p := range plain {
+ if p >= 128 {
+ return plain, lib.CPError{"Has high ASCII values"}
+ }
+ }
+
+ return plain, nil
+ }
+
+ // Encrypt atleast 3 blocks of plain text.
+ c := encrypt(lib.StrToBytes(
+ "As soon as you are born they make you feel small"))
+
+ // Modify cipher.
+ copy(c[32:48], c[0:16]) // C_3 <- C_1
+ copy(c[16:32], lib.FillBytes(0, 16)) // C_2 <- 0
+
+ // Try decrypting.
+ p, err := decrypt(c)
+ if err != nil {
+ // Has high ASCII values; recover key.
+ k := lib.FixedXORBytes(p[0:16], p[32:48])
+ if lib.BytesEqual(k, key) {
+ fmt.Printf("Recovered key: %v\n", k)
+ return
+ }
+ }
+ fmt.Printf("Could not recover key\n")
+}
+
+// Output:
+// Recovered key: [62 228 155 158 92 189 217 142 58 118 162 140 165 41 152 237]
diff --git a/cryptopals.go b/cryptopals.go
index 79df27d..312d5aa 100644
--- a/cryptopals.go
+++ b/cryptopals.go
@@ -71,5 +71,7 @@ func main() {
challenge.C25()
case 26:
challenge.C26()
+ case 27:
+ challenge.C27()
}
}