// THIS IS PROBABLY ONE OF THE BEST func EncryptAES_CTR(plainText, key string) (string, error) { keyBytes := secutils.ASCIIStringToBytes(key) plaintextBytes := secutils.ASCIIStringToBytes(plainText) block, err := aes.NewCipher(keyBytes) if err != nil { panic(err) } // The IV needs to be unique, but not secure. Therefore it's common to // include it at the beginning of the ciphertextBytes. ciphertextBytes := make([]byte, BlockSize+len(plaintextBytes)) iv := ciphertextBytes[:BlockSize] if _, err := io.ReadFull(rand.Reader, iv); err != nil { panic(err) } stream := cipher.NewCTR(block, iv) stream.XORKeyStream(ciphertextBytes[BlockSize:], plaintextBytes) hexCipherText := secutils.BytesToHex(ciphertextBytes) return hexCipherText, nil // CTR mode is the same for both encryption and decryption, so we can // also decrypt that ciphertextBytes with NewCTR. // plaintext2 := make([]byte, len(plaintextBytes)) // stream = cipher.NewCTR(block, iv) // stream.XORKeyStream(plaintext2, ciphertextBytes[aes.BlockSize:]) }
func EncryptAES_CBC_Manual(plainText, key string) []byte { keyBytes := secutils.ASCIIStringToBytes(key) plainTextBytes := secutils.ASCIIStringToBytes(plainText) blocks := len(plainTextBytes) / BlockSize mod := len(plainTextBytes) % BlockSize if mod != 0 { blocks++ } iv := make([]byte, BlockSize) if _, err := io.ReadFull(rand.Reader, iv); err != nil { panic(err) } var buffer bytes.Buffer previousBlock := iv buffer.Write(iv) for block := 0; block < blocks; block++ { // this is the last block which may need padding if block == blocks-1 { start := block * BlockSize data := plainTextBytes[start:] // just make sure it is padded // the Pkcs7 function takes care of double check it originalData := Pkcs7(data, BlockSize) // XOR with the previous block xored := secutils.XorBytes(originalData, previousBlock) cipherBlock := Encrypt_Block(xored, keyBytes) buffer.Write(cipherBlock) } else { start := block * BlockSize end := start + BlockSize // XOR with the previous block originalData := plainTextBytes[start:end] xored := secutils.XorBytes(originalData, previousBlock) // Encrypt with the XORED data and assign the result to the previous block for the next cycle ! cipherBlock := Encrypt_Block(xored, keyBytes) // #### THIS IS REALLY IMPORTANT !!!!! // otherwise it is completely broken !!!! previousBlock = cipherBlock buffer.Write(cipherBlock) } } return buffer.Bytes() }
//d7ab340a60337584edbab1a82d6b0977 func TestDecryptAES_CBC_Manual(t *testing.T) { text := secutils.HexStringToBytes("a6af0c64422b96e8923c1ebe819e82553e8e38f74e1693a9cde95502229ddcc0") key := secutils.ASCIIStringToBytes("YELLOW SUBMARINE") //cipherTextBytes, _ := DecryptAES_CBC(text, key) cipherTextBytes := DecryptAES_CBC_Manual(text, key) //cipherHex := secutils.BytesToHex(cipherTextBytes) fmt.Printf("6. Test DecryptAES_CBC Manual: %s\n", cipherTextBytes) }
func TestDencryptAES_CBC(t *testing.T) { text := "YELLOW SUBMARINE!" key := "YELLOW SUBMARINE" cipherTextBytes, _ := EncryptAES_CBC(text, key) keyBytes := secutils.ASCIIStringToBytes(key) clearText, _ := DecryptAES_CBC(cipherTextBytes, keyBytes) fmt.Printf("2. Test DencryptAES_CBC: %s\n", clearText) }
func EncryptAES_CBC(plainText, key string) ([]byte, error) { keyBytes := secutils.ASCIIStringToBytes(key) plainTextBytes := secutils.ASCIIStringToBytes(plainText) plainTextLen := len(plainTextBytes) mod := plainTextLen % BlockSize // CBC mode works on blocks so plaintexts may need to be padded to the // next whole block. For an example of such padding, see // https://tools.ietf.org/html/rfc5246#section-6.2.3.2. Here we'll // assume that the plaintext is already of the correct length. if mod != 0 { //panic("plaintext is not a multiple of the block size") plainTextBytes = Pkcs7(plainTextBytes, BlockSize) //fmt.Printf("%s\n", plainTextBytes) plainTextLen = len(plainTextBytes) } block, err := aes.NewCipher(keyBytes) if err != nil { panic(err) } // The IV needs to be unique, but not secure. Therefore it's common to // include it at the beginning of the ciphertext. ciphertextBytes := make([]byte, BlockSize+plainTextLen) iv := ciphertextBytes[:BlockSize] if _, err := io.ReadFull(rand.Reader, iv); err != nil { panic(err) } mode := cipher.NewCBCEncrypter(block, iv) mode.CryptBlocks(ciphertextBytes[BlockSize:], plainTextBytes) // It's important to remember that ciphertexts must be authenticated // (i.e. by using crypto/hmac) as well as being encrypted in order to // be secure. //hexCipherText := secutils.BytesToHex(ciphertextBytes) return ciphertextBytes, nil }
func TestEncryptAES_CBC(t *testing.T) { text := "YELLOW SUBMARINE" key := "YELLOW SUBMARINE" cipherTextBytes, _ := EncryptAES_CBC(text, key) keyBytes := secutils.ASCIIStringToBytes(key) clearText, _ := DecryptAES_CBC(cipherTextBytes, keyBytes) fmt.Printf("1. Test EncryptAES_CBC: %s\n", clearText) if clearText != text { t.Error("Test EncryptAES_CBC and DencryptAES_CBC error !") } }
// This should use a different key for every AES BLOCK !!!! // Otherwise it is INSECURE! func EncryptAES_ECB_Manual(plainText, key string) []byte { keyBytes := secutils.ASCIIStringToBytes(key) plainTextBytes := secutils.ASCIIStringToBytes(plainText) blocks := len(plainTextBytes) / BlockSize mod := len(plainTextBytes) % BlockSize if mod != 0 { blocks++ } var buffer bytes.Buffer for block := 0; block < blocks; block++ { // this is the last block which may need padding if block == blocks-1 { start := block * BlockSize data := plainTextBytes[start:] // just make sure it is padded // the Pkcs7 function takes care of double check it data = Pkcs7(data, BlockSize) cipherBlock := Encrypt_Block(data, keyBytes) buffer.Write(cipherBlock) } else { start := block * BlockSize end := start + BlockSize data := plainTextBytes[start:end] cipherBlock := Encrypt_Block(data, keyBytes) buffer.Write(cipherBlock) } } return buffer.Bytes() }