func TestCBCBitflip(t *testing.T) { as := []byte("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") admin := xor.Xor([]byte(";admin=true;\x00\x00\x00\x00"), []byte("AAAAAAAAAAAAAAAA")) key, iv, ct := EncryptComment(string(as)) modblock := xor.Xor(ct[32:48], admin) ctpre := ct[:32] ctpost := ct[48:] newct := append(ctpre, modblock...) newct = append(newct, ctpost...) if !DecryptComment(key, iv, newct) { t.Errorf("CBCBitflip: Failed to create admin block!") } }
func CBCDecrypt(key, iv, ciphertext []byte) (plaintext []byte) { for len(ciphertext) > 0 { ct_block := ciphertext[:16] pt_block := ECBDecrypt(key, ct_block) pt_block = xor.Xor(iv, pt_block) plaintext = append(plaintext, pt_block...) iv = ct_block ciphertext = ciphertext[16:] } return plaintext }
func CBCEncrypt(key, iv, plaintext []byte) (ciphertext []byte) { for len(plaintext) > 0 { pt_block := plaintext[:16] intermediate_block := xor.Xor(iv, pt_block) ct_block := ECBEncrypt(key, intermediate_block) ciphertext = append(ciphertext, ct_block...) iv = ct_block plaintext = plaintext[16:] } return ciphertext }
func HammingWeight(bs1 []byte, bs2 []byte) int { var weight int bs := xor.Xor(bs1, bs2) for _, b := range bs { var i byte for i = 1; i < 128; i = i << 1 { if b&i == i { weight += 1 } } } return weight }
func CTREncrypt(key []byte, nonce uint64, plaintext []byte) (ciphertext []byte) { ctr := uint64(0) for len(plaintext) > 0 { ctr_block := new(bytes.Buffer) binary.Write(ctr_block, binary.LittleEndian, nonce) binary.Write(ctr_block, binary.LittleEndian, ctr) ctr++ var pt_block []byte if len(plaintext) < 16 { pt_block = plaintext[:len(plaintext)] plaintext = plaintext[len(plaintext):] } else { pt_block = plaintext[:16] plaintext = plaintext[16:] } ks_block := ECBEncrypt(key, ctr_block.Bytes()) ct_block := xor.Xor(pt_block, ks_block[:len(pt_block)]) ciphertext = append(ciphertext, ct_block...) } return }
//CBC Padding Oracle Attack function. Takes an oracle function and a ciphertext to manipualate func CBCPaddingOracle(oracle func(input []byte) bool, ciphertext []byte) { //["AAAAAAAAAAAAAAAA", "AAAAAAAAAAAA\x04\x04\x04\x04"] //PT[n] = \x01 //CT[n-1] xor PT[n] = IS[n] //CT[n-1] xor IS[n] = PT[n] //Assuming AES256 bs := 16 blocks := Blocks(bs, ciphertext) //Panic for empty input ciphertext if len(blocks) < 2 { panic(errors.New("PANIC!!!! Your ciphertext input is too small")) } fmt.Println("DEBUG: Number of blocks:", len(blocks)) //Iterating over blocks plaintext := make([]byte, 0) for i := 0; i < len(blocks)-1; i++ { //Ciphertext block to modify to find valid padding mod_block := make([]byte, bs) copy(mod_block, blocks[i]) expected_padding := byte(1) intermediate_state := make([]byte, bs) //Loop that builds the intermediate state block for j := len(mod_block) - 1; j >= 0; j-- { var iterator_byte byte //Loop that determines the appropriate intermediate state byte at each point in the block skip_byte := mod_block[j] for { if iterator_byte == skip_byte { iterator_byte++ continue } mod_block[j] = iterator_byte two_blocks := append(mod_block, blocks[i+1]...) if oracle(two_blocks) { intermediate_state[j] = iterator_byte ^ expected_padding expected_padding++ for k := len(mod_block) - 1; k >= j; k-- { mod_block[k] = expected_padding ^ intermediate_state[k] } iterator_byte = 0 break } iterator_byte++ //We have looped through all bytes if iterator_byte == 0 { break } //We have tried all expected padding values if expected_padding == 17 { break } } } fmt.Println("IS:") fmt.Println(intermediate_state) fmt.Println() plaintext = append(plaintext, xor.Xor(blocks[i], intermediate_state)...) } fmt.Println("PLAINTEXT:") fmt.Println(plaintext) fmt.Println(string(plaintext)) }
func CTREditAttack(ciphertext []byte, oracle func([]byte, int, []byte) []byte) []byte { ctLen := len(ciphertext) nulls := make([]byte, ctLen) keystream := oracle(ciphertext, 0, nulls) return xor.Xor(keystream, ciphertext) }