summaryrefslogtreecommitdiffstats
path: root/challenge
diff options
context:
space:
mode:
Diffstat (limited to 'challenge')
-rw-r--r--challenge/c27.go87
1 files changed, 87 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]