tdo

Dicing the onion
git clone git@abtrout.com:tdo.git
Log | Files | Refs | README

commit 3e942aad1e42e2e9380a7203b6187a827477b1fa
parent 5449f48e21138128d9936541f3d5dbf2eeba3b76
Author: david cochran <about.trout@gmail.com>
Date:   Tue,  4 Nov 2025 06:32:35 -0800

add layer5 solution

Diffstat:
Acmd/layer5/decode.go | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+), 0 deletions(-)

diff --git a/cmd/layer5/decode.go b/cmd/layer5/decode.go @@ -0,0 +1,86 @@ +package main + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "encoding/binary" + "errors" + "log" + "os" + + "github.com/abtrout/tdo" +) + +func main() { + bs, err := tdo.DecodePipedInput() + if err != nil { + log.Fatalf("Failed to read layer input: %v", err) + } + + // Split input based on instructions. + kek := bs[0:32] + keyIV, keyCT := bs[32:40], bs[40:80] + ctIV, ct := bs[80:96], bs[96:] + // Decrypt the key with kek and keyIV. + block, err := aes.NewCipher(kek) + if err != nil { + log.Fatalf("Failed to make NewCipher: %v", err) + } + key, err := KeyUnwrap(block, keyIV, keyCT) + if err != nil { + log.Fatalf("Failed to unwrap key: %v", err) + } + // Decrypt the ct with key and iv. + block, err = aes.NewCipher(key) + if err != nil { + log.Fatalf("Failed to make NewCipher: %v", err) + } + out := make([]byte, len(ct)) + stream := cipher.NewCTR(block, ctIV) + stream.XORKeyStream(out, ct) + + if _, err := os.Stdout.Write(out); err != nil { + log.Fatalf("Failed to write decoded output: %v", err) + } +} + +// Key Unwrap is not implemented in the standard library. +// https://datatracker.ietf.org/doc/html/rfc3394#section-2.2.2 +func KeyUnwrap(block cipher.Block, iv, ct []byte) ([]byte, error) { + // setup + a := make([]byte, 8) + copy(a, ct[0:8]) + n := (len(ct) / 8) - 1 // n+1 blocks + r := make([][]byte, n) + for i := range r { + r[i] = ct[(i+1)*8 : (i+2)*8] + } + // unwrap + ctr := make([]byte, 8) + for j := 5; j >= 0; j-- { + for i := len(r) - 1; i >= 0; i-- { + binary.BigEndian.PutUint64(ctr, uint64(n*j+i+1)) + // a = a ^ ctr + for i := range a { + a[i] ^= ctr[i] + } + // b = Decrypt(a || r[i]) + b := append(a, r[i]...) + block.Decrypt(b, b) + // reset for next round + copy(a, b[0:8]) + copy(r[i], b[8:16]) + } + } + // verify + if !bytes.Equal(a, iv) { + return nil, errors.New("iv mismatch") + } + // output + var res []byte + for _, b := range r { + res = append(res, b...) + } + return res, nil +}