c6 "cryptopals/Set1/challenge6"
c7 "cryptopals/Set1/challenge7"
c11 "cryptopals/Set2/challenge11"
c9 "cryptopals/Set2/challenge9"
prefix = c11.RandBytes(int(c11.RandByte()) % 64)
unknown, err = c6.Decodebase64LineByLine("./Set2/challenge12/12.txt")
panic("Cannot decode the file.")
//fmt.Println("Block size: ", size)
cipher := EncryptOracle(make([]byte, size*4))
if !c11.IsECB(cipher, size) {
fmt.Println("ECB detected.")
prBlocks, prBytes := detectPrefix(size)
prLen := prBlocks*size + prBytes
//fmt.Println("Prefix blocks: ", prBlocks, "\nPrefix bytes: ", prBytes)
cipher = EncryptOracle(make([]byte, 0))
secrectLen := len(cipher) - prLen
fmt.Println("Length of the message and padding: ", secrectLen)
// End prefix with aligned block. We will prepend all inputs with mockup to
// discard first blocks in the cipher as prefix part.
mockup := make([]byte, size-prBytes)
// discard this amount of bytes in cipher
discard := prLen + len(mockup)
fill := make([]byte, size)
unknown := make([]byte, secrectLen)
for blockLen := 0; blockLen < secrectLen/size; blockLen++ {
for i := 1; i < 17 && blockLen*size+i-1 < secrectLen; i++ {
pos := blockLen*size + i - 1
copy(fill[len(fill)-i:], unknown[:i])
copy(fill, unknown[pos-size+1:pos])
cipher := EncryptOracle(append(mockup, fill[:size-i]...))
ideal := cipher[discard+blockLen*size : discard+(blockLen+1)*size]
// Determine the last byte by trying all possible values and comparing
// resulting cipher with ideal.
for b := 0; b < 256; b++ {
cipher := EncryptOracle(append(mockup, fill...))
if bytes.Equal(ideal, cipher[discard:discard+size]) {
fmt.Println("Cannot find byte at Position ", pos)
if len(unknown)-pos < 16 {
fmt.Printf("Only %d bytes remaining, might be padding.\n", len(unknown)-pos)
fmt.Printf("Decoded with padding:\n%#v\n", string(unknown))
fmt.Printf("Decoded without padding:\n%#v\n", string(unknown))
func EncryptOracle(input []byte) []byte {
src := append(prefix, input...)
src = append(src, unknown...)
block, err := aes.NewCipher([]byte(key))
src = c9.PKCS(src, keySize)
dst := make([]byte, len(src))
c7.EncryptAES_ECB(block, dst, src)
prevLen := len(EncryptOracle(make([]byte, 1)))
for i := 2; i < 32; i++ {
cipher := EncryptOracle(make([]byte, i))
if prevLen != len(cipher) {
size = len(cipher) - prevLen
func detectPrefix(size int) (int, int) {
prev := EncryptOracle(make([]byte, 0))
cipher := EncryptOracle(make([]byte, 1))
for j := 0; j < len(cipher)-size; j += size {
if bytes.Equal(prev[j:j+size], cipher[j:j+size]) {
// Prefix contains at least blocks amount of data,
// now, detect how many more additional bytes. The block after blocks
// will stop changing when enough bytes were added to the input.
for i := 1; i <= size+1; i++ {
cipher := EncryptOracle(input)
if bytes.Equal(prev[check:check+size], cipher[check:check+size]) {
return blocks, size - added