TripleDES Decryption truncating last character - encryption

I have a .NET class that implements TripleDES encryption and decryption. The code is too much to post here. However, the problem is that while encryption is OK, decryption is inconsistent depending on the length of the original plaintext. I know that encryption is OK since other triple DES tools also give same value.
Specifically, the last character is being cut off from the resulting plain text if the Length of the original Plaintext was 8,16,24,32,40 etc i.e 8n.
The encryption mode is CBC
The key size is 24 chars(192bits)
The IV is 8 chars

The problem is because the (un)padding algorithm is not correct.
(3)DES encrypts/decrypts blocks of 8 bytes. As not all texts are precisely 8 bytes, the last block must contain bytes that are not original from the plain text. Now the trick is to find out which one is the last character of the plain text. Sometimes the length of the plain text is known beforehand - then the padding characters can be anything really.
If the length of the plain text is not known then a deterministic padding algorithm must be used, e.g. PKCS5Padding. PKCS5Padding always performs padding, even if the plaintext is N * blocksize in bytes. The reason for this is simple: otherwise it doesn't know if the last byte is plain text or padding: 41 41 41 41 41 41 41 41 08 08 08 08 08 08 08 08 would be 8 'A' characters, with 8 padding bytes.
It seems that either the unpadding algorithm is not well implemented, or that a non-deterministic padding algorithm is deployed.

Related

Interpret double written as hex

I am working with doubles (64-bit) stored in a file by printing the raw bytes from the C# representation. For example the decimal number 0.95238095238095233 is stored as the bytes "9e e7 79 9e e7 79 ee 3f" in hex. Everything works as expected, I can write and read, but I would like to be able to understand this representation of the double myself.
According to the C# documentation https://learn.microsoft.com/en-us/dotnet/api/system.double?view=netframework-4.7.2#explicit-interface-implementations and wikipedia https://en.wikipedia.org/wiki/Double-precision_floating-point_format the first bit is supposedly the sign with 0 for positive and 1 for negative numbers. However, no matter the direction I read my bytes, the first bit is 1. Either 9 = 1001 or f = 1111. I am puzzled since 0.95... is positive.
As a double check, the following python code returns the correct decimal number as well.
unpack('d', binascii.unhexlify("9ee7799ee779ee3f"))
Can anyone explain how a human can read these bytes and get to 0.95238095238095233?
Figured it out, the collection of bytes are read like a 64-bit number (first bit on the left), but each byte is read like a string(first bit on the right). So my bytes should be read "3F" first, 3F reads left to right, so I'm starting with the bits 0011 1111 etc. This gives the IEEE 754 encoding as expected: First bit is the sign, next 11 bits the exponent, and then the fraction.

Length of AES encrypted data

I have a data that needs to be stored in a database as encrypted, the maximum length of the data before encryption is 50 chars (English or Arabic), I need to encrypt the data using AES-128 bit, and store the output in the database (base64string).
How to know the length of the data after encryption?
Try it with your specified algorithm, block size, IV size, and see what size output you get :-)
First it depends on the encoding of the input text. Is it UTF8? UTF16?
Lets assume UTF8 so 1 Byte per character means 50 Bytes of input data to your encryption algorithm. (100 Bytes if UTF16)
Then you will pad to the Block Size for the algorithm. AES, regardless of key size is a block of 16 Bytes. So we will be padded out to 64 Bytes (Or 112 for UTF 16)
Then we need to store the IV and header information. So that is (usually, with default settings/IV sizes) another 16Bytes so we are at 80 Bytes (Or 128 for UTF16)
Finally we are encoding to Base64. I assume you want string length, since otherwise it is wasteful to make it into a string. So Base 64 bloats the string using the following formula: Ceil(bytes/3) * 4. So for us that is Ceil(80/3) = 27 * 4 = 108 characters (Or 172 for UTF 16)
Again this is all highly dependent on your choices of how you encrypt, what the text is encoded as, etc.
I would try it with your scenario before relying on these numbers for anything useful.

Is it possible to ensure that strings encrypted with AES128/CBC/PKCS5Padding never have trailing equals characters

Is there a deterministic way to ensure that any encrypted/encoded String created with AES128/CBC/PKCS5Padding never has '=' characters padding the end?
Given a crypto util which is a black-box:
String originalValue = "this is a test";
String encryptedValue = TheCryptoUtil.encrypt(original);
The encryptedValue will often look like:
R2gDfGwGvkqZWHH4UF81rg==
Is there a way of varying "originalValue" e.g. by padding the input with whitespaces, such that, regardless of the keys used by TheCryptoUtil, the output will not have any "=" at the end?
Yes, it is possible. I have no idea why you want to do this, but it is possible. Things to keep in mind:
The output of AES-128 with PKCS5Padding will always be some multiple of 16. That is, len(ciphertext) % 16 == 0.
The equals signs that you see on the end of the ciphertext have nothing to do with AES. They are actually base64 padding.
Base64 takes, as input, blocks of 3 bytes and converts them into blocks of 4 characters, where these output 4 characters are any of the 64 defined characters.
This means that the number of bytes of output determines whether or not the base64 of the output will have padding. For example, if you encrypt the message The quick brown fox jumps over the lazy dog., I'd say it is fairly likely (depending on your "black box encryption") that the result will not have any base64 padding.
So, the fact that base64 always produces an encoded string of length that is divisible by 4 means that we can easily determine that length of the original with or without padding. In fact, base64 padding is only part of the spec to help with concatenation issues.
I expect you'll be able to figure out the rest from here!
Luke's answer is correct to say that AES has nothing to do with the padding, it is however missing some of the information below.
Base 64 usually produces padding if the input is not dividable by 3. The padding is just there to make sure that the output only consists of blocks of 4 characters from the base 64 alphabet. Base 64 encodes 64 values or 6 bits per character. 3 bytes are 24 bits, which is dividable by 6 giving you 4 characters required.
The naive thing to do would be to adjust the AES output so that it is dividable by 3. This can however require up to 34 additional padding bytes on the input of AES/CBC/PKCS5Padding, which is stupidity at best.
Not all base 64 schemes actually use padding, so the easiest way of accomplishing this is simply to select a base 64 scheme that doesn't perform the padding at all. Java for instance has a withoutPadding() configuration method.
If the base 64 encoder cannot handle that then it is possible to simply remove the padding after it has been generated. Before decoding you can add back one or two '=' characters until you count a number of base 64 characters (excluding whitespace, see notes) that is dividable by 4.
Note that base 64 usually also uses / and + in the alphabet (there are only 2 * 26 + 10 = 62 characters if you use upper-/lowercase chars & digits). You could look up a URL-safe base 64 encoding - called base64url - if that is what you are after.
Base64 for MIME may also use spaces and end-of-line characters, by the way.

AES- ECB using DataPower

I have a requirement where in I get a HEX string which is 32 character long. I need to encrypt it with AES-128-ECB and get an Hex string with is again 32 character long.
I have been asked to convert the 32 char hex string to binary stream(to get 16 bytes of data) and then encrypt it using AES-ECB(to get 16 bytes of encrypted data) and then convert this 16 bytes of encrypted data to 32 char hex string.
I came across this article to achieve AES-ECB encryption.
https://www.ibm.com/developerworks/community/blogs/HermannSW/entry/gatewayscript_modules_aes?lang=en
​
Kindly let me know how to achieve this.
Other than the actual code you have the concept, for more detailed help you will need to make a best-effort attempt and add that code to the question along with error information and input/output test data (in hex).
Note that you need to ensure that padding is not added, some AES implementations add padding by default and will add a block of (PKCS#7) padding to data that is an exact multiple of the block size (16-bytes for AES).
Note: ECB mode, it is insecure when the key is used more than once and there is a similarity in the data. See ECB mode, scroll down to the Penguin.

What type of hash (or encryption) is this?

I am reverse engineering an unfortunate legacy application. I know the following:
username => hashFunction() => 8BYUW6iFeL9mmSBW7xjzMw~~
password => hashFunction() => VszQfe5n0+CooePc7CS9kw~~
The hashes always seem to be 22 characters in length. The system is a legacy microsoft .net application. I have reason to believe that they are reverseable as well (but this may not be true).
The two trailing tildes make me feel like I should be able to identify this. How do I begin to figure out what type of hashing is used?
If the 'hashFunction' function is part of the legacy application, you could use a reflection tool like .net reflector to reverse the code to see what the function is doing.
Just a wild guess
64^21 < 2^128 <= 64^22
You need 22 characters for a base-64 encoding of a 128-bit hash.
The above argument will also work if you replace 64 with any integer from 57 up to 68. Base-67 encodings are not common I assume but it doesn't harm to have that in mind.
Your samples seem to have at least 63 characters (26 upper, 26 lowercase, 10 digits, plus the plus-sign).
Assuming the trailing '~' characters are fillers (which is not the usual case (the usual is '=')) the username comes out to:
f0 16 14 5b a8 85 78 bf 66 99 20 56 ef 18 f3 33
and the password comes out to:
56 cc d0 7d ee 67 d3 e0 a8 a1 e3 dc ec 24 bd 93
in hex. This agrees with the the 128 bits of the other posters. It sounds like the output of an AES-128 encryption or MD5 hash. With a sample this small and no idea what the source was, this is kind of where we have to leave it. Since you said you thought they might be reversible, that kind of points to AES-128. Without a bigger sample and no input data, that is all that can be done with it.
I tried doing an MD5 hash of the strings "username" and "password" and they come out to different values. If it was encrypted with AES, we are out of luck without some more hints.
Good luck,
/Bob Bryan
Here is an interesting value:
Fj83STvXE+6q57GVjIi9aQ==
I just happen to know it is PI to 37 places (times 1E37)
3141592653589793238462643383279502884
Not all base64 values are hashed or encrypted. Without some knowledge of the process that resulted in the value, it is impossible to do much with a random 128 bit string.
Regards,
/Bob Bryan

Resources