openssl AES encryption adds a blocksize worth of bytes to output - bash

I'm trying to encrypt with openssl on the console to match output generated by another implementation of AES. All details are known. I'm using AES in 128-bit CBC mode. Weirdly enough, irrespective of the file size, the output will be 16 bytes larger. I think openssl is appending some kind of padding.
In the direction to the other implementation it's not that much of a problem as I can drop the last 16 bytes, but the other way around is as I can't invent the bytes that openssl will probably check for validity.
How do I tell openssl not to do that?
Commandline:
openssl enc -aes-128-cbc -K <pre-shared key in hex> -in rawfile.bin -out encfile.enc -iv <pre-shared IV in hex>

openssl enc has a -nopad option. I've not used it, but it sounds relevant.
-nopad
disable standard block padding

Related

Generate OpenSSL subject_name hash in ruby

I've investigated 30261296 however I'm still at a loss to find a way to generate the same results in Ruby with the openssl and/or digest gems. The OpenSSL output I'm trying to replicate in ruby is as follows:
$ openssl x509 -noout -subject_hash -in DigiCertSHA2SecureServerCA.pem
85cf5865
In reading many things, I believe this hash is generated from the Subject: portion of the certificate, which is like the distinguished name. In this certificates case something to the effect of:
$ openssl x509 -noout -subject -in DigiCertSHA2SecureServerCA.crt
subject=C = US, O = DigiCert Inc, CN = DigiCert SHA2 Secure Server CA
Attempting to SHA-1 encode that on the command line or in Ruby (which represents this as /C=US,/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA when using the openssl gem) has not yeilded the same has results displayed by OpenSSL.
I'm trying to do this more natively in Ruby to avoid shelling out to openssl if possible since openssl and digest come along with the ruby env. In the end I need this to generate the hash directory tree ... i.e. 85cf5865.0 (hash + '.0').
The CA I'm hasing is DigiCertSHA2SecureServerCA.crt - DER encoded. I converted DER to PEM because openssl command line uses that without the additional -inform der switch. It doesn't appear to matter to Ruby's openssl gem.
This turns out to be pretty straightforward, since Ruby’s OpenSSL bindings includes the OpenSSL::X509::Name#hash method, which is exactly what we want.
require 'openssl'
# Read the certificate.
cert = OpenSSL::X509::Certificate.new(File.binread("DigiCertSHA2SecureServerCA.crt"))
# Get the subject, which is an OpenSSL::X509::Name object.
name = cert.subject
# hash returns an integer, we want the hex string so call to_s(16).
puts name.hash.to_s(16) #=> 85cf5865
The integer will be positive since OpenSSL returns an unsigned int, so we can just use to_s(16) and don’t need to worry about converting negative values.

OpenSSL key length too short in Ruby, not in Bash

I originally experimented with a simple encryption script in Bash and it worked pretty much as expected. However, I'm now trying to do the same thing in Ruby and the Ruby version seems function a little differently.
Bash
Encrypt
echo 'hello' | openssl enc -aes-256-cbc -a
Password: mypass
Result: U2FsdGVkX19rERfOXiKs97FgwIkLy3+ttZzaHkEoQyE=
Decrypt
echo 'U2FsdGVkX19rERfOXiKs97FgwIkLy3+ttZzaHkEoQyE=' | openssl aes-256-cbc -d -a
Password: mypass
Result: hello
Ruby
require "openssl"
require 'base64'
cipher = OpenSSL::Cipher.new('AES-256-CBC').encrypt
cipher.key = 'mypass'
This is what I've attempted in Ruby so far but I receive a OpenSSL::Cipher::CipherError: key length too short error. I would like to mimic Bash as much as possible.
OpenSSL uses a (largely undocumented) password based key derivation function (PBKDF) called EVP_BytesToKey using an 8 byte salt and an iteration count of 1. A magic and salt of 8 bytes each are prefixed to the ciphertext (check the first bytes of the result to see the magic).
Obviously "mypass" cannot be a correct key for AES. AES keys are 16, 24 or 32 byte binary values for the 128, 192 and 256 key sizes. You can however specify a key directly using the -K switch on the command line to make the code compatible with the Ruby Cipher object. In that case you need to specify the key using binary (a file) or hexadecimals for the openssl command line and in Ruby. You would also need to specify an IV.
Alternatively you would have to find an EVP_BytesToKey implementation for Ruby, but note that this is an old OpenSSL specific function with a completely insecure iteration count.

program linked with lcrypto is many times slower than openssl command

I have a simple C program for aes256 encryption. It is linked with openssl library (-lcrypto). The core of the program are following few lines:
AES_set_encrypt_key(key32 ,256 ,&aes_ks3);
while( len = fread( buf ,1 ,4096, fp) ){
if( 4096 != len )
break;
AES_cbc_encrypt(buf ,buf ,len ,&aes_ks3 ,iv ,AES_ENCRYPT);
fwrite(buf ,1 ,len ,wfp);
}
AES_cbc_encrypt(buf ,buf ,len+padding_len ,&aes_ks3, iv,AES_ENCRYPT);
fwrite(buf ,1 ,len+padding_len ,wfp);
I am only using standard openssl library functions for encryption (ie. I am not using my own functions). I can encrypt same file, using same key and IV with openssl command:
openssl enc -aes-256-cbc -in FILE.in -out FILE.out -K $key -iv $iv
And I get identical output file (thus verifying that my program works correctly).
However, my program consistently runs is 4-5 times slower than the openssl command. They are both using the same routines, abd are both linked with the same library.
How is that possible?
How can I investigate why?
UPDATE:
Here are the actual numbers for encrypting same file with 1) openssl, 2) my program:
1) openssl:
real 0m0.238s
user 0m0.196s
sys 0m0.040s
2) my program:
real 0m1.006s
user 0m0.964s
sys 0m0.040s
By calling the AES functions directly, you lose all the optimizations provided by the EVP layer. In particular, the EVP layer supports AES intrinsics, which makes a huge difference on CPUs that support them.

Decrypting Windows Crypto API RSA Ciphertext With OpenSSL

I have created a C++ program that encrypts some bytes with a RSA 2048 key.
The output of the program is 256 bytes and everything seems to work fine.
However I've been completely unable to figure out how to decrypt this with openssl.
I've been told that I might need to reverse the byte order so it becomes big endian but it doesn't seem to help. (I assume reversing the bytes order means turning 1F 02 C8 into F1 20 8C etc.)
I'm mainly getting the following error from openssl.
openssl rsautl -in output.bin -inkey privatekey -decrypt
rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02:rsa_pk1.c:190:
Here is a code snippet of my encryption for anyone that interested (I've tried it with final as true also)
BYTE crapBuffer[1200] = {0x33,0x1F,0x22,0x34,0x33,0x1F,0x22,0x34,0x33,0x1F,0x22,0x34,0x33,0x1F,0x22,0x34,0x33,0x1F,0x22,0x34};
DWORD dataLen = 20;
CryptEncrypt(publicKey,0,false,0,(BYTE *)crapBuffer,&dataLen,1200);
Any help would be greatly appreciated,

How to specify passphrases for P12 to PEM file conversion without interaction.

I'm trying to convert a P12 file to a PEM file. When I execute the command, the terminal asks me for three things:
P12 passphrase (I type it in, hit enter)
PEM passphrase (type it in, hit enter)
PEM passphrase confirm (type it in, hit enter)
I know I can execute a sudo command all in one shot by using the following:
echo sudopassword | sudo rm -rf /file.p12;
How can I add all three values in one shot? Thanks
Can you explain what these P12 files are? I found this link which deals with the conversion of pkcs12 Cert/key files to .PEM format using openssl. (http://gridsite.org)
Key to the answer is:
Use -passin file:... and -passout file:... for unattended processing
It's my guess that you will have to specify the -passin file:P12passphrase and -passout file PEMpassphrase options for this case.
This little test confirms how an input passphrase can be specified through a file:<...> parameter. This helps to hide such phrases from any over the shoulder attacks. Don't forget to restrict access to such files. Even though it's a common feature of most openssl commands, it's not explicitly mentioned and it is key to the original question. The full list of options is below.
$ openssl pkcs12 -passin file:P12phrase
Can't open file P12phrase
Error getting passwords
(I leave it to the OP to construct the full command.)
Below are all supported options for the pkcs12 subcommand:
$ openssl pkcs12 help
Usage: pkcs12 [options]
where options are
-export output PKCS12 file
-chain add certificate chain
-inkey file private key if not infile
-certfile f add all certs in f
-CApath arg - PEM format directory of CA's
-CAfile arg - PEM format file of CA's
-name "name" use name as friendly name
-caname "nm" use nm as CA friendly name (can be used more than once).
-in infile input filename
-out outfile output filename
-noout don't output anything, just verify.
-nomacver don't verify MAC.
-nocerts don't output certificates.
-clcerts only output client certificates.
-cacerts only output CA certificates.
-nokeys don't output private keys.
-info give info about PKCS#12 structure.
-des encrypt private keys with DES
-des3 encrypt private keys with triple DES (default)
-aes128, -aes192, -aes256
encrypt PEM output with cbc aes
-nodes don't encrypt private keys
-noiter don't use encryption iteration
-maciter use MAC iteration
-twopass separate MAC, encryption passwords
-descert encrypt PKCS#12 certificates with triple DES (default RC2-40)
-certpbe alg specify certificate PBE algorithm (default RC2-40)
-keypbe alg specify private key PBE algorithm (default 3DES)
-keyex set MS key exchange type
-keysig set MS key signature type
-password p set import/export password source
-passin p input file pass phrase source
-passout p output file pass phrase source
-engine e use engine e, possibly a hardware device.
-rand file:file:...
load the file (or the files in the directory) into
the random number generator
-CSP name Microsoft CSP name
-LMK Add local machine keyset attribute to private key
It's unlikely that these commands are reading from stdin. It's more likely that they're reading directly from the terminal. This allows them to set a mode that doesn't echo the password to the screen. Try echoing your input to /dev/tty.
Beyond that, you'll need to use something like expect / pexect to control these. Those projects were build specifically for this purpose.
Openssl has a -stdin optoin to read its input from stdin. This works:
tmp=`mktemp`
cat > $tmp <<EOF
$1
EOF
cat $tmp | openssl req -out CSR.csr -new -newkey rsa:2048 -nodes -keyout privateKey.key
I've used cat and a here-document to avoid putting the password on the commandline.
I used openssl pkcs12 -in Certificates.p12 -out sampleCore.pem -nodes and it was working for me.
Have you tried just echoing three lines? It would probably work
echo $'P12 passphrase\nPEM passphrase\nPEM passphrase confirm' | cmd
Although I feel I must point out that echoing passwords like this is highly insecure. Not only does the password end up in your bash history file, but it's also visible to anyone else on the system who runs ps.

Resources