Different encrypted outputs in AES implementations? [duplicate] - c

I've compiled some AES implementation code from this site, it's supposed to perfrom a 128 bits key encryption. I tested the encryption/decryption programs which work OK together.
However if I encrypt anything with the mentioned code and then try to decrypt it by openssl tool built-in in linux, I just can't get decrypt it, it even logs me the bad magic number error. Same, if I encrypt anything with openssl and try to decrypt with the code won't work. I tried with both cbc ecb.
If they're both implementing AES, shouldn't it work same way?

it looks like the C code is using ECB and does no padding. so try encrypting a message (a multiple) of 16 bytes followed by 16 bytes of value 16 (pkcs#7 padding). or use a message (a multiple) of 16 bytes and --nopad in openssl (more likely to work). also, use aes-128-ecb or whatever it's called.
a block cipher works on "chunks" of text - in this case, it's 16 characters long. so if you don't want to worry about padding you need to give an exact number of chunks.
also, ecb mode (doing each chunk in turn with no extra processing) isn't secure for many uses. see the wikipedia article (look at the penguin photos).
[edit:] [edit 2:]
> echo -n "abcdabcdabcdabcd" > msg
> wc msg
0 1 16 msg
> openssl enc -aes-128-ecb -nopad -in msg -K 0 -S "" -iv ""
[noise]
> openssl enc -aes-128-ecb -nopad -in msg -K 0 -S "" -iv "" | wc
0 1 16
try the above yourself and see if the other code decrypts it (edit 2 sets the key explicitly, and removes IV and salt - not sure what the latter two are for in this case).
[edit 3:]
as far as i can tell, the problem is related to the way that the password is converted to a key. openssl seems to be doing something extra that i can't get rid of unless i specify a key as hex (-K 0). and if i do that, the other program doesn't work (needs a password).
sorry, i'm out of ideas.

Related

Convert code using openssl to use mbedtls

I am trying to convert some C code written to run on a Mac to an embedded device that does not have any encryption libraries. The code for the Mac is using libcrypto. I tried building libcrypto from openssl sources for the embedded device but I get hundreds of errors due to function pointer prototypes not matching. openssl is riddled with huge macros. As an alternative I am now trying to use mbedtls but I have not been able to get a decrypt function to work.
The code I am trying to port is a bit odd. It has what it calls a public key and is actually calling RSA_public_encrypt() with no padding to decrypt data. As a test, I changed the Mac code to call RSA_public_decrypt() and it worked so I assume the key is symmetric. The key it is using looks like this:
"-----BEGIN PUBLIC KEY-----\n"
5 lines of Base64 strings
"-----END PUBLIC KEY-----\n"
For mbedtls I am using mbedtls_pk_parse_public_key() to parse the key. If I inspect the low level RSA key structure after parsing the key there is a 128 byte N component and a 16 byte E component. I get the same key data with both openssl and mbedtls so it appears that the key is parsed properly. When decrypting on the Mac with RSA_public_decrypt(), the input and output are both 128 bytes. For mbedtls, I am calling mbedtls_pk_decrypt() to decrypt but when I trace through the code it calls mbedtls_rsa_rsaes_pkcs1_v15_decrypt() which forces the padding to be 11 bytes.
So my questions are: 1) exactly what kind of "public" key contains only N and E components and uses no padding; 2) Am I calling the correct mbedtls decryption function?
EDIT: Tried another approach and my output buffer just gets filled with zeros.
mbedtls_rsa_context rsa;
mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);
mbedtls_rsa_import_raw(&rsa, modulus, sizeof(modulus), NULL, 0, NULL, 0, NULL, 0, exp, sizeof(exp));
mbedtls_rsa_complete(&rsa);
mbedtls_rsa_public(&rsa, inBfr, outBfr);
mbedtls_rsa_free(&rsa);
EDIT 2: My ultimate target is an embedded device with an ARM processor but I was testing on Windows to see if mbedtls would work. I started with VS 2010 because that is what was being used for the project I am working on. I switched to VS 2015 and the 2nd approach of importing the raw key data and calling mbedtls_rsa_public() worked perfectly. I guess the VS 2010 compiler just isn't good enough. I then ported the code to the devlepment system for my embedded device and it also worked.
The equivalent of OpenSSL's RSA_public_encrypt(…, RSA_NO_PADDING) would be mbedtls_rsa_public. The function mbedtls_pk_encrypt only lets you access encryption mechanisms based on RSA (RSAES-PKCS1-v1_5 and RSAES-OAEP), not the raw RSA primitive (“textbook RSA” a.k.a. “RSA with no padding”).
You need to call mbedtls_pk_parse_public_key to parse the key, then get a pointer to the RSA key object with mbedtls_pk_rsa, and call mbedtls_rsa_public using this RSA key object.
mbedtls_pk_context pk;
mbedtls_pk_init(&pk);
mbedtls_rsa_context *rsa = mbedtls_pk_rsa(&pk);
mbedtls_rsa_public(&rsa, inBfr, outBfr);
mbedtls_pk_free(&pk);
I think this should work from your description, but obviously I can't test this without sample data.

Contiguous Hex file generation using GCC

I have a Hex file for STM32F427 that was built using GCC(gcc-arm-none-eabi) version 4.6 that had contiguous memory addresses. I wrote boot loader for loading that hex file and also added checksum capability to make sure Hex file is correct before starting the application.
Snippet of Hex file:
:1005C80018460AF02FFE07F5A64202F1D00207F5F9
:1005D8008E4303F1A803104640F6C821C2F2000179
:1005E8001A460BF053F907F5A64303F1D003184652
:1005F8000BF068F907F5A64303F1E80340F6FC1091
:10060800C2F2000019463BF087FF07F5A64303F145
:10061800E80318464FF47A710EF092FC07F5A643EA
:1006280003F1E80318460EF03DFC034607F5A64221
:1006380002F1E0021046194601F0F2FC07F56A5390
As you can see all the addresses are sequential. Then we changed the compiler to version 4.8 and i got the same type of Hex file.
But now we used compiler version 6.2 and the Hex file generated is not contiguous. It is somewhat like this:
:10016000B9BC0C08B9BC0C08B9BC0C08B9BC0C086B
:10017000B9BC0C08B9BC0C08B9BC0C08B9BC0C085B
:08018000B9BC0C08B9BC0C0865
:1001900081F0004102E000BF83F0004330B54FEA38
:1001A00041044FEA430594EA050F08BF90EA020FA5
As you can see after 0188 it is starting at 0190 means rest of 8 bytes(0189 to 018F) are 0xFF as they are not flashed.
Now boot loader is kind of dumb where we just pass the starting address and no of bytes to calculate the checksum.
Is there a way to make hex file in contiguous way as compiler 4.6 and compiler 4.8? the code is same in all the three times.
If post-processing the hex file is an option, you can consider using the IntelHex python library. This lets you manipulate hex file data (i.e. ignoring the 'markup'; record type, address, checksum etc) rather than as lines, will for instance create output with the correct line checksum.
A fast way to get this up and running could be to use the bundled convenience scripts hex2bin.py and bin2hex.py:
python hex2bin.py --pad=FF noncontiguous.hex tmp.bin
python bin2hex.py tmp.bin contiguous.hex
The first line converts the input file noncontiguous.hex to a binary file, padding it with FF where there is no data. The second line converts it the binary file back to a hex file.
The result would be
:08018000B9BC0C08B9BC0C0865
becomes
:10018000B9BC0C08B9BC0C08FFFFFFFFFFFFFFFF65
As you can see, padding bytes are added where the input doesn't have any data, equivalent to writing the input file to the device and reading it back out. Bytes that are in the input file are kept the same - and at the same address.
The checksum is also correct as changing the length byte from 0x08 to 0x10 compensates for the extra 0xFF bytes. If you padded with something else, IntelHex would output the correct checksum
You can skip the the creation of a temporary file by piping these: omit tmp.bin in the first line and replacing it with - in the second line:
python hex2bin.py --pad=FF noncontiguous.hex | python bin2hex.py - contiguous.hex
An alternative way could be to have a base file with all FF and use the hexmerge.py convenience script to merge gcc's output onto it with --overlap=replace
The longer, more flexible way, would be to implement your own tool using the IntelHex API. I've used this to good effect in situations similar to yours - tweak hex files to satisfy tools that are costly to change, but only handle hex files the way they were when the tool was written.
One of many possible ways:
Make your hex file with v6.2, e.g., foo.hex.
Postprocess it with this Perl oneliner:
perl -pe 'if(m/^:(..)(.*)$/) { my $rest=16-hex($1); $_ = ":10" . $2 . ("FF" x $rest) . "\n"; }' foo.hex > foo2.hex
Now foo2.hex will have all 16-byte lines
Note: all this does is FF-pad to 0x10 bytes. It doesn't check addresses or anything else.
Explanation
perl -pe '<some script>' <input file> runs <some script> for each line of <input file>, and prints the result. The script is:
if(m/^:(..)(.*)$/) { # grab the existing byte count into $1
my $rest=16 - hex($1); # how many bytes of 0xFF we need
$_ = ":10" . $2 . ("FF" x $rest) . "\n"; # make the new 16-byte line
# existing bytes-^^ ^^^^^^^^^^^^^^-pad bytes
}
Another solution is to change the linker script to ensure the preceding .isr_vector section ends on a 16 byte alignment, as the mapfile reveals that the following .text section is 16 byte aligned.
This will ensure there is no unprogrammed flash bytes between the two sections
You can use bincopy to fill all empty space with 0xff.
$ pip install bincopy
$ bincopy fill foo.hex
Use the -gap-fill option of objcopy, e.g.:
arm-none-eabi-objcopy --gap-fill 0xFF -O ihex firmware.elf firmware.hex

Encryption Program That Works With NodeJs and mbedtls

First, let me start by stating that I am not a cryptographer by any means, and I am not very good at writing c code either, so please excuse me if the answer to this question is obvious or answered. I am developing a messaging program and cannot use TLS on the target platform. As a result, I need to find a way to encrypt each message using a symmetric pre shared key cipher, like AES.
I am seeking a method to encrypt and decrypt data between an mbedtls program (such as aescrypt2) on one end, and a nodejs program on the other. Mbedtls, formerly polarssl, is a library which provides encryption for embedded devices. Included with the source code are some sample programs, like aescrypt2, rsaencrypt, ecdsa and crypt_and_hash.
Aescrypt2 works fine when the resulting encrypted data is also decrypted using aescrypt2, but I cannot seem to get data encrypted with aescrypt to decrypt using nodejs crypto or any other program for that matter, including openssl. For example:
echo 'this is a test message' >test.txt
aescrypt 0 test.txt test.out hex:E76B2413958B00E193
aescrypt 1 test.out test.denc hex:E76B2413958B00E193
cat test.denc
this is a test message
With openssl:
openssl enc -in out.test -out outfile.txt -d -aes256 -k E76B2413958B00E193
bad magic number
Some sample node code that doesn't currently work
var crypto = require('crypto');
var AESCrypt = {};
AESCrypt.decrypt = function(cryptkey, iv, encryptdata) {
encryptdata = new Buffer(encryptdata, 'base64').toString('binary');
var decipher = crypto.createDecipheriv('aes-256-cbc', cryptkey, iv),
decoded = decipher.update(encryptdata, 'binary', 'utf8');
decoded += decipher.final('utf8');
return decoded;
}
AESCrypt.encrypt = function(cryptkey, iv, cleardata) {
var encipher = crypto.createCipheriv('aes-256-cbc', cryptkey, iv),
encryptdata = encipher.update(cleardata, 'utf8', 'binary');
encryptdata += encipher.final('binary');
encode_encryptdata = new Buffer(encryptdata, 'binary').toString('base64');
return encode_encryptdata;
}
var cryptkey = crypto.createHash('sha256').update('Nixnogen').digest(),
iv = 'a2xhcgAAAAAAAAAA',
buf = "Here is some data for the encrypt", // 32 chars
enc = AESCrypt.encrypt(cryptkey, iv, buf);
var dec = AESCrypt.decrypt(cryptkey, iv, enc);
console.warn("encrypt length: ", enc.length);
console.warn("encrypt in Base64:", enc);
console.warn("decrypt all: " + dec);
This results in either errors or garbage text every time. I have tried tweaking a variety of things as well.
I've tried this a hundred different ways, including using the -pass pass:password arg to no avail. Using nodejs, I have either gotten bad decrypt errors, or garbled nonsense back upon decryption. I have tried following many tutorials on the net, such as this one, and suggestions from this thread, and everything else I can find. I have read that different encryption programs use different standards, so compatibility across platforms/programs/languages is not always guaranteed, but I imagine somebody has been in this predicement before and knows a solution?
How would I, using nodejs, decrypt data encrypted by aescrypt2 (or a program like it)? I have only been able to make it work using a system exec call and having node execute aescrypt2 to decrypt/encrypt the data, which is not ideal, as it slows things down considerably. I am open to using a different program than aescrypt2. The only requirements are that it must run on Linux, cannot use openssl libs (because they are not supported on the target system), the program should be small and simple, due to space limitations, and foremost, the encryption/decryption needs to be compatible with nodejs. Any help would be much appreciated.
How would I, using nodejs, decrypt data encrypted by aescrypt2 (or a program like it)?
Sorry to say, but there's no better answer than: by doing the exact same thing that aescrypt2 does when decrypting a file. You've linked to the source by yourself, so just perform the same steps in node.js as they do in C in the decrypt branch.
First of all, get familiar with the layout of the file containing the encrypted data:
/*
* The encrypted file must be structured as follows:
*
* 00 .. 15 Initialization Vector
* 16 .. 31 AES Encrypted Block #1
* ..
* N*16 .. (N+1)*16 - 1 AES Encrypted Block #N
* (N+1)*16 .. (N+1)*16 + 32 HMAC-SHA-256(ciphertext)
*/
So you need to extract the IV, the encrypted blocks and the HMAC from the file, not try to decrypt the whole thing as you try with openssl (your openssl example also does not use the right IV but rather tries to derive it from the key provided - read the man page).
Next, get the key right. The actual key used to encrypt/decrypt is not the one provided on the command line, but rather 8192 iterations of hashing the IV with the key passed on the command line, using SHA256.
Finally, they decrypt, using AES-256-ECB (your openssl and node.js examples use CBC!), every 16 bytes and XOR the result with the pervious 16 bytes (the IV is used for the first 16 bytes).
There's maybe more to it, I just listed the most obvious things I saw when reading through the aescrypt2.c code.
So my advise is: try to write the same logic in node.js and try to find node.js crypto calls for the respective mbedtls counterparts.
I'm not a crypto expert, but I bet that the aescrypt implementation has so many steps that feel complicated (like generating the actual key used), because they know how to do crypto and are just doing it the right way.

What are bag attributes and how can i generate them?

while converting some certificates from keystore to openssl/pem I noticed for the first time that there are "Bag Attributes" prepended to the certs.
The look like this:
Bag Attributes
friendlyName: CN=PositiveSSL CA,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB
subject=/C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=PositiveSSL CA
issuer=/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware
Do they serve any function?
I noticed that I like them because they make my chain-files (a concatenation of certificates) more clear. Sadly the ca certs I download don't have them.
So how do I generate them?
To be exact, you apparently mean converting (or just reading) with the openssl pkcs12 (import) utility a PKCS#12 file, which can be supported by Java as a keystore but was not the default (update) until Java9 in 2017. PKCS#12 was designed and normally is used for a privatekey and the cert(s) (usually multiple) for that key, although the format is flexible enough to allow lone cert(s). OpenSSL commandline pkcs12 -export requires a privatekey, although it will add "extra" certs, and a program calling the API can apparently do no privatekey. In my experience, Java didn't support lone cert(s) in PKCS#12 before version 8, and in my 8 and 9 has two attributes: pkcs9.friendlyName and 2.16.840.1.113894.746875.1.1 which is apparently an Oracle-defined trustedKeyUsage. Most lone certs are not stored, or downloaded, as PKCS#12.
PKCS#12 is defined in terms of several (slightly different) "bag" structures that contain various things, primarily privatekeys and certs with optional attributes attached that are unsurprisingly called "bag attributes"; your case (apparently) has only cert(s). These attributes follow the now-conventional structure of an arbitrary number of pairs of OID plus value depending on the OID. Note in your display only friendlyName is a bag attribute, indicated because it is indented under the heading.
The subject= and issuer= lines are fields from the cert itself which the openssl pkcs12 (import) utility extracts and prints for convenience. If that is sufficient, you can display them for any cert with the x509 utility; in particular if you want to have them before the PEM-encoded cert "blob" in the way pkcs12 output does, use openssl x509 -in infile -subject -issuer -out outfile. This does one cert, so if you have a chain in a PEM file you need to split it apart and do each cert separately, and possibly combine again afterwards; for example something like
# split into files cert_1, cert_2, etc.
$ awk <chain.pem -va="openssl x509 -subject -issuer >cert_"
'/^-----BEGIN/{b=a (++n);x=1}x{print|b}/^-----END/{close(b);x=0}'
# output entire "bag" to stdout (with blank lines between certs)
$ awk <chain.pem -va="openssl x509 -subject -issuer" \
'/^-----BEGIN/{b=a;x=1}x{print|b}/^-----END/{close(b);x=0;print""}'
As a comparison, openssl s_client -showcerts does something very similar: it outputs subject and issuer with each cert blob from the received chain, labelling them with a level number, "s:" and "i:".

Issue with crypt C API on AIX 7.1

I am writing a password reset utility on AIX (7.1.0.0) and I need to support SMD5, SSHA256, SSHA512 and BLOWFISH password hash algorithms. I have successfully implemented the code for SMD5, SSHA256 and SSHA512. However, for BLOWFISH algorithm the 'crypt' API still returns normal DES hash and not the BLOWFISH hash. I tried different prefixes in salt value - {sblowfish} {sblowfish}08$ {SBLOWFISH} {SBLOWFISH}08$. However, I still don't get blowfish hash. For, AIX 5.3 {sblowfish} prefix in salt value works and I get required hash. However, for AIX 7.1 it doesn't work.
The format for the salt value I am using is as follows -
MD5 - {smd5}<randomly generated 8 characters>$
SHA256 - {ssha256}06$<randomly generated 8 characters>$
SHA512 - {ssha512}06$<randomly generated 8 characters>$
BLOWFISH - {sblowfish}08$<randomly generated 22 characters>$
I then pass the user password and salt value to the 'crypt' API in 'C'.
crypt(password, salt);
For MD5, SHA256 and SHA512 I get the password hash which is compliant to the corresponding algorithm.
However, for BLOWFISH salt, the 'crypt' API rejects the salt and instead returns normal DES hash though i have the blowfish in the system.
Can anybody please help out here? Thanks in advance.

Resources