package main import ( "crypto/aes" //"crypto/cipher" //"crypto/rand" "crypto/sha256" "fmt" "log" //"io" "encoding/hex" //"io/ioutil" "os" ) func encrypt() { //block size for SHA-256 is 64 bytes blockSize := 64 keyMacHex := "6b6579" //TODO: parse from command line (last 16 bytes) //parse hexadecimal key string into byte slice keyMac, err := hex.DecodeString(keyMacHex) if err != nil { log.Fatal(err) } //generate inner and outer padded key var outPad []byte var inPad []byte for i := 0; i < blockSize; i++ { //XOR bits of key and pads (key is assumed padded with 0s if too short) if i < len(keyMac) { outPad = append(outPad, keyMac[i] ^ '\x5c') inPad = append(inPad, keyMac[i] ^ '\x36') } else { outPad = append(outPad, '\x00' ^ '\x5c') inPad = append(inPad, '\x00' ^ '\x36') } } msgHex := fmt.Sprintf("%x", "The quick brown fox jumps over the lazy dog") //TODO: parse from file //parse hexadecimal message string into byte slice msg, err := hex.DecodeString(msgHex) if err != nil { log.Fatal(err) } //two hash objects for the inner and outer hash h256_inner := sha256.New() h256_outer := sha256.New() //hash the concatenation of inner pad and message inMsg := append(inPad, msg...) h256_inner.Write(inMsg) //hash the concatenation of outer pad and inner hash outMsg := append(outPad, h256_inner.Sum(nil)...) h256_outer.Write(outMsg) //get final 32-byte MAC tag mac := h256_outer.Sum(nil) //concatenate message and MAC tag mPad1 := append(msg, mac...) //fmt.Printf("%x\n", msg) //get padding string using PKCS #5 to make message a multiple of AES block size (16) n := len(mPad1) % 16 var pStr []byte for i := 0; i < (16 - n); i++ { pStr = append(pStr, byte(16-n)) } mPad2 := append(mPad1, pStr...) blockIndex := 0 var cipherText []byte //test key key := []byte{'\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03'} //test IV iv := [16]byte{'\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03', '\x03'} //encrypt for every block in plaintext for blockIndex < len(mPad2) { //initialize new slice to hold current block's XOR var xorText []byte for i := blockIndex; i < blockIndex + 16; i++ { //use IV bits to XOR in first block //use previous ciphertext block to XOR for remaining blocks if blockIndex == 0 { xorText = append(xorText, iv[i] ^ mPad2[i]) } else { xorText = append(xorText, cipherText[i-16] ^ mPad2[i]) } } block, err := aes.NewCipher(key) //key should be 16 bytes of input parameter if err != nil { log.Fatal(err) } //encrypt XOR'ed block cipherBlock := make([]byte, 16) block.Encrypt(cipherBlock, xorText) //append to current ciphertext cipherText = append(cipherText, cipherBlock...) //increment starting index of block blockIndex += 16 } fmt.Printf("%x\n", cipherText) } func decrypt() { } func main() { if len(os.Args) < 2 { log.Fatal("Invalid # of arguments.") } mode := os.Args[1] if mode == "encrypt" { encrypt() } else if mode == "decrypt" { decrypt() } else { log.Fatal("Invalid mode.") } }
We use cookies to provide and improve our services. By using our site, you consent to our Cookies Policy. Accept Learn more