decode.go (1889B)
1 package main 2 3 import ( 4 "bytes" 5 "crypto/aes" 6 "crypto/cipher" 7 "encoding/binary" 8 "errors" 9 "log" 10 "os" 11 12 "github.com/abtrout/tdo" 13 ) 14 15 func main() { 16 bs, err := tdo.DecodePipedInput() 17 if err != nil { 18 log.Fatalf("Failed to read layer input: %v", err) 19 } 20 21 // Split input based on instructions. 22 kek := bs[0:32] 23 keyIV, keyCT := bs[32:40], bs[40:80] 24 ctIV, ct := bs[80:96], bs[96:] 25 // Decrypt the key with kek and keyIV. 26 block, err := aes.NewCipher(kek) 27 if err != nil { 28 log.Fatalf("Failed to make NewCipher: %v", err) 29 } 30 key, err := KeyUnwrap(block, keyIV, keyCT) 31 if err != nil { 32 log.Fatalf("Failed to unwrap key: %v", err) 33 } 34 // Decrypt the ct with key and iv. 35 block, err = aes.NewCipher(key) 36 if err != nil { 37 log.Fatalf("Failed to make NewCipher: %v", err) 38 } 39 out := make([]byte, len(ct)) 40 stream := cipher.NewCTR(block, ctIV) 41 stream.XORKeyStream(out, ct) 42 43 if _, err := os.Stdout.Write(out); err != nil { 44 log.Fatalf("Failed to write decoded output: %v", err) 45 } 46 } 47 48 // Key Unwrap is not implemented in the standard library. 49 // https://datatracker.ietf.org/doc/html/rfc3394#section-2.2.2 50 func KeyUnwrap(block cipher.Block, iv, ct []byte) ([]byte, error) { 51 // setup 52 a := make([]byte, 8) 53 copy(a, ct[0:8]) 54 n := (len(ct) / 8) - 1 // n+1 blocks 55 r := make([][]byte, n) 56 for i := range r { 57 r[i] = ct[(i+1)*8 : (i+2)*8] 58 } 59 // unwrap 60 ctr := make([]byte, 8) 61 for j := 5; j >= 0; j-- { 62 for i := len(r) - 1; i >= 0; i-- { 63 binary.BigEndian.PutUint64(ctr, uint64(n*j+i+1)) 64 // a = a ^ ctr 65 for i := range a { 66 a[i] ^= ctr[i] 67 } 68 // b = Decrypt(a || r[i]) 69 b := append(a, r[i]...) 70 block.Decrypt(b, b) 71 // reset for next round 72 copy(a, b[0:8]) 73 copy(r[i], b[8:16]) 74 } 75 } 76 // verify 77 if !bytes.Equal(a, iv) { 78 return nil, errors.New("iv mismatch") 79 } 80 // output 81 var res []byte 82 for _, b := range r { 83 res = append(res, b...) 84 } 85 return res, nil 86 }