AES Compatibility with Python

76 views
Skip to first unread message

Dwight Kulkarni

unread,
Apr 27, 2023, 11:43:47 AM4/27/23
to Crypto++ Users
Hello everyone,

Today I am trying to resolve an AES incompatibility with Python.  I am using CFB Mode. I use the same base64 key and iv on both and I printed out the bytes and they are the same.

I load in the same key/iv into both of them. When I print out the bytes they are different.

This encrypt_aes is returning a string, I'm concerned maybe there is a string conversion when decoding UTF-8/ASCII or something like that, so I want to first do just raw bytes encryption, not a string ?

Question is how do I change the encrypt_aes to return a byte* rather than string ?


std::string encrypt_aes(std::string message, SecByteBlock key, SecByteBlock iv) {
try {
CFB_Mode<AES>::Encryption e;
std::string cipher;
e.SetKeyWithIV(key, key.size(), iv);
StringSource ss(message, true, new StreamTransformationFilter(e, new StringSink(cipher)));
return cipher;
}
catch (CryptoPP::Exception e) {
std::cerr << e.what() << std::endl;
return "";
}
}


class AESModeOfOperationCFB(AESSegmentModeOfOperation):
    '''AES Cipher Feedback Mode of Operation.

       o A stream-cipher, so input does not need to be padded to blocks,
         but does need to be padded to segment_size

    Also see:
       o https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_feedback_.28CFB.29
       o See NIST SP800-38A (http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf); section 6.3'''


    name = "Cipher Feedback (CFB)"

    def __init__(self, key, iv, segment_size = 1):
        if segment_size == 0: segment_size = 1

        if iv is None:
            self._shift_register = [ 0 ] * 16
        elif len(iv) != 16:
            raise ValueError('initialization vector must be 16 bytes')
        else:
          self._shift_register = _string_to_bytes(iv)

        self._segment_bytes = segment_size

        AESBlockModeOfOperation.__init__(self, key)

    segment_bytes = property(lambda s: s._segment_bytes)

    def encrypt(self, plaintext):
        if len(plaintext) % self._segment_bytes != 0:
            raise ValueError('plaintext block must be a multiple of segment_size')

        #plaintext = _string_to_bytes(plaintext)

        # Break block into segments
        encrypted = [ ]
        for i in xrange(0, len(plaintext), self._segment_bytes):
            plaintext_segment = plaintext[i: i + self._segment_bytes]
            xor_segment = self._aes.encrypt(self._shift_register)[:len(plaintext_segment)]
            cipher_segment = [ (p ^ x) for (p, x) in zip(plaintext_segment, xor_segment) ]

            # Shift the top bits out and the ciphertext in
            self._shift_register = _concat_list(self._shift_register[len(cipher_segment):], cipher_segment)

            encrypted.extend(cipher_segment)

        return encrypted #_bytes_to_string(encrypted)

    def decrypt(self, ciphertext):
        if len(ciphertext) % self._segment_bytes != 0:
            raise ValueError('ciphertext block must be a multiple of segment_size')

        #ciphertext = _string_to_bytes(ciphertext)
        print("starting decryption .. ")
        # Break block into segments
        decrypted = [ ]
        for i in xrange(0, len(ciphertext), self._segment_bytes):
            #print("dec 1")
            cipher_segment = ciphertext[i: i + self._segment_bytes]
            #print("dec 2")
            xor_segment = self._aes.encrypt(self._shift_register)[:len(cipher_segment)]
            #print("dec 3")
            plaintext_segment = [ (p ^ x) for (p, x) in zip(cipher_segment, xor_segment) ]
            #print("dec 4")

            # Shift the top bits out and the ciphertext in
            self._shift_register = _concat_list(self._shift_register[len(cipher_segment):], cipher_segment)
            #print("dec 5")

            decrypted.extend(plaintext_segment)
            #print("dec 6")

        print("finished decrypt")
        return decrypted#_bytes_to_string(decrypted)




Jeffrey Walton

unread,
Apr 27, 2023, 12:15:56 PM4/27/23
to cryptop...@googlegroups.com
On Thu, Apr 27, 2023 at 11:43 AM Dwight Kulkarni <dwi...@realtime-7.com> wrote:
>
> Today I am trying to resolve an AES incompatibility with Python. I am using CFB Mode. I use the same base64 key and iv on both and I printed out the bytes and they are the same.
>
> I load in the same key/iv into both of them. When I print out the bytes they are different.
> [...]

https://www.cryptopp.com/wiki/CFB_Mode#Feedback_Size

Jeff

Dwight Kulkarni

unread,
Apr 27, 2023, 12:58:16 PM4/27/23
to Crypto++ Users
Hi Jeff,
 

This worked. Thanks !
 



std::string encrypt_aes(std::string message, SecByteBlock key, SecByteBlock iv) {
try {
cout <<" in encrypt aes " <<endl;
AlgorithmParameters params = MakeParameters(Name::FeedbackSize(), 1 /*16*8 -bits*/)
(Name::IV(), ConstByteArrayParameter(iv));
CFB_Mode<AES>::Encryption e;
std::string cipher;
e.SetKey(key, key.size(), params);
StringSource ss(message, true, new StreamTransformationFilter(e, new StringSink(cipher)));
cout << " returning cipher " << endl;
return cipher;
}
catch (CryptoPP::Exception e) {
std::cerr << e.what() << std::endl;
return "";
}
}

AlgorithmParameters params = MakeParameters(Name::FeedbackSize(), 1 /*8-bits*/) (Name::IV(), ConstByteArrayParameter(iv));
CFB_Mode< AES >::Encryption enc; enc.SetKey( key, key.size(), params ); // CFB mode must not use padding. Specifying // a scheme will result in an exception StringSource ss1( plain, true, new StreamTransformationFilter( enc, new StringSink( cipher ) ) // StreamTransformationFilter ); // StringSource


Reply all
Reply to author
Forward
Message has been deleted
0 new messages