I have a use case where we're streaming log data to a file using a simple NodeJS app. We'd like to be able to encrypt this data as we're streaming it and then decrypt it later as required using OpenSSL or similar.
What we're doing a basically as below:
var crypto = require('crypto'),
algorithm = 'aes256',
password = 'password';
var fs = require('fs');
var Readable = require('stream').Readable
var r = new Readable
r.push('This is a test')
r.push(null)
var encrypt = crypto.createCipher(algorithm, password);
var decrypt = crypto.createDecipher(algorithm, password)
var w = fs.createWriteStream('file.out');
//Write encrypted stream to file. Decrypt with openssl fails with 'bad magic number'
r.pipe(encrypt).pipe(w)
//Decrypt using cipher library. Decrypted text displays as expected
//r.pipe(encrypt).pipe(decrypt).pipe(w)
Assuming we're just encrypting the data as we're reading it in I'd assumed we could decrypt it using open OpenSSL e.g.
openssl enc -d -aes256 -in file.out -out file.out.decrypted
But this is just giving me the error
Bad magic number
Any help would be really appreciated.
Looking at the documentation of the crypto.createCipher() function, it mentions that the OpenSSL EVP_BytesToKey() function is used for deriving the key from the passphrase, just like the openssl enc app does. So that seems compatible.
However, that same documentation does not mention that any salt is applied and the function does not seem to have the possibility to pass a salt in as a parameter either. Therefore, you will have to pass the -nosalt option to openssl enc to make it work, as in:
openssl enc -d -aes256 -nosalt -in file.out -out file.out.decrypted
You can simulate what is happening by just using the openssl enc tool, with and without expecting a salt on the decrypt end:
Your current situation:
$ echo -n 'This is a test' | openssl enc -aes256 -nosalt -pass pass:password | openssl enc -d -aes256 -pass pass:password
bad magic number
Adding -nosalt when decrypting:
$ echo -n 'This is a test' | openssl enc -aes256 -nosalt -pass pass:password | openssl enc -d -aes256 -nosalt -pass pass:password
This is a test
By default, the OpenSSL encrypted file format starts with an 8-byte "magic number", the US-ASCII encoding of "Salted__". That's followed by another 8-byte value that's hashed with the password to derive the encryption key and IV for the message. Your NodeJS code isn't deriving the key the same way or providing the necessary header, so it won't work.
OpenSSL's key derivation algorithm is insecure and non-standard. If you derive the key from a password yourself using a good key derivation algorithm like PBKDF2 (or, better yet, randomly choose a key), you can provide it (encoded in hexadecimal) to the enc command with the -K option, along with the IV using the -iv option. I haven't checked to see if you also need the -nosalt option to avoid complaints about the magic number in this case.
Related
I executed the below command and generated a random key
openssl rand -hex 45
and it generated me
524ec7a76ad9140087232b8e278c03d4bc121fdfd0e4f13a6bd16959a81e2d289b5edcf0848b435fc201fc4c1c
I then encrypted me file with Open ssl using this. When i tried to decrypt i just changed last two characters like this
524ec7a76ad9140087232b8e278c03d4bc121fdfd0e4f13a6bd16959a81e2d289b5edcf0848b435fc201fc4c2d
and now when it tried to decrypt, it still works and decrypt the file... what could be wrong ? Below is my decrypt command
export my_key=524ec7a76ad9140087232b8e278c03d4bc121fdfd0e4f13a6bd16959a81e2d289b5edcf0848b435fc201fc4c2d
openssl enc -aes-256-cbc -d -in my-secret-encrypted.enc -K $my_key -iv 9 > my-secret.txt
I want to encrypt a parameter with openssl using public.key and decrypt with private.key using linux command line. But the requirement is that the output after encryption should be just in one line so that I can transfer it or send it over to other server. File creation as output is not required.
I have seen rsautl but it gives output in a file or hex dump, which is not possible in my case as I require the output in one line. Please provide the necessary help.
pkeyutl sends its output to a file only if you ask for it. If you do not specify an output file (with the -out option) it sends its output to the standard output. But as it is binary, you cannot easily manipulate it and, moreover, it could be that there are end-of-lines in the output stream.
In order to solve this you can pipe the output of pkeyutl to base64. If your version of base64 wraps its output you'll have to concatenate to get the result on one line only. Some versions (e.g. GNU coreutils 8.10) have a -w0 option that prevents wrapping and produces a single line output (without end-of-line). Example with openssl version 1.0.2a:
echo "foo" | openssl pkeyutl -encrypt -pubin -inkey bob_id_rsa.pub | base64 -w0
where bob_id_rsa.pub is bob's public key in openssl format. You can decrypt with:
base64 -d | openssl pkeyutl -decrypt -inkey bob_id_rsa
where bob_id_rsa is bob's private key. Complete example with encryption followed by decryption:
bar=$( echo foo | openssl pkeyutl -encrypt -pubin -inkey bob_id_rsa.pub | base64 -w0 )
cue=$( echo $bar | base64 -d | openssl pkeyutl -decrypt -inkey bob_id_rsa )
echo $cue
foo
I have a set of public/private keys, that works flawless when encrypting/decrypting some data using only one of the 2 ways for both encryption and decryption.
I still have no luck trying to encrypt the data with the one of the two and decrypt it with the other.
Example schenario:
a) I create some encrypted data using the public key with the following node.js code:
#!/usr/bin/env node
var NodeRSA = require('node-rsa');
var fs = require('fs');
function createUsingPubKey(Pub, data) {
var pk = new NodeRSA();
pk.importKey(Pub);
encrypted = pk.encrypt(data, 'base64');
return encrypted;
}
var sampledata = "SECRET STUFF";
var genkey = createUsingPubKey(fs.readFileSync('id_rsa.pub'), sampledata)
console.log(genkey);
b) Then i try to decrypt it using openssl utility with this:
node test.js | openssl base64 -d -A | openssl rsautl -inkey id_rsa
But i get:
RSA operation error
1068:error:0406706C:rsa routines:RSA_EAY_PUBLIC_DECRYPT:data greater than mod len:.\crypto\rsa\rsa_eay.c:680:
I thought that they probably would use different algorithms for the encryption/decryption procedure so i headed to the node-rsa documentation here:
https://www.npmjs.com/package/node-rsa and i found this option:
encryptionScheme — padding scheme for encrypt/decrypt. Can be
'pkcs1_oaep' or 'pkcs1'. Default 'pkcs1_oaep'.
I then tried to decrypt passing the -oaep option in openssl util like this:
node test.js | openssl base64 -d -A | openssl rsautl -oaep -inkey id_rsa
But i still get:
RSA operation error
5216:error:0406706C:rsa routines:RSA_EAY_PUBLIC_DECRYPT:data greater than mod len:.\crypto\rsa\rsa_eay.c:680:
My knowledge on cryptography is really basic. Any help would be appreciated :)
EDIT 1:
The node.js module can be found here:
https://github.com/rzcoder/node-rsa
EDIT 2:
As Maarten Bodewes requested, here is some sample data:
Plaintext data to be encrypted:
You're no good, you're no good, you're no good Baby, you're no good
(I'm gonna say it again) You're no good, you're no good, you're no
good Baby, you're no good
A private key generated with
openssl genrsa -out key 512
-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBALOUBygyX11BsDoEIKoZzn2/HAXPorNR/X8wCDaBlcPtOHxKAZFk
Vra1+Pem1urtSlnEqc07DwAP6v0GEGHpxbkCAwEAAQJAGAZ17qrOl2tyaFClDhzl
w20OErj0y4jsoVeLwb8UimG48JslS14hfM9XxE/fG6qypN8u7LUhlnBC68ZcQ9Jg
AQIhAORaVlB7trWp6n7dETvdY9J2p8ubOuyLTX0BA2jF8agxAiEAyVHzDWQPWx/s
gt+ABErqN+ZUWS016DD34QUVGyp9nAkCIQC39JpSDcd7gx1YA8jNXCT9N/8mg6+t
PO84g2d2sPdjEQIgXwWMF/TzfopJ4tfFH8GQXYQcqd66A/cg+Jeih6j9kqkCIGD4
hBAO0haqnqeSO65Mm1IjY/6Z77pKxzJAGys5XeXk
-----END RSA PRIVATE KEY-----
And its equivalent pub key
openssl rsa -in key -pubout > key.pub
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALOUBygyX11BsDoEIKoZzn2/HAXPorNR
/X8wCDaBlcPtOHxKAZFkVra1+Pem1urtSlnEqc07DwAP6v0GEGHpxbkCAwEAAQ==
-----END PUBLIC KEY-----
The above plaintext data encrypted with the given public key using the node.js rsa library:
nbp1tBlcev9PvD3xDmEQkcBd8ewNxW8Xm7oZWVcsFika3dU/H3VFoxdeH75DPy4/xLvN1Gxqfb/bXTnfKZLZBYV1q4XfmR4p3ji41MAybpMiEl5h4fSFYacg5SiQ/KxxmQr0SLs4rttwcbaGBLG6rcIU+6SSYBYu1GhC+XBlBG94zbqFV9ZvohEbnlnqDDW1Kg9hGT9/vBBtiLEQnTiKDwztIgY3DhqadsVW0g37PFFwuQKXtHw/lQqrRhc+Pb03g+Oq8nIpX8eaurL8lo3lZNkhlY4NfFCYwP7v12MYwSrMeWPMe20LDDQ6NXbJnrsLGl5x08aYn7liS5qsYdtqRpYv+JbJc3EoXIZEyHv17gU1R0OmLsSd/Teln9VAvM+jt4jwQjlvE1WF8g9Qc/WNo28RR4KaNOvUpLDwfuc3gTgkG90ac8EchmKB3LAgU47kQComyphuPAI/G4phqeXOeYnbBrB1aqwxAkAwOIvanGjCY6FXlV8Cve1jao0ejQ0EFE1180yjhltgh5U2EErQLDd5S4y5YLbLz4xIiKo3k06Yktk4dSJsBalHPxi7Z+kofjT3KdeHyGMynodGzOmH5CaAAS2enZpp2VytcawlDu84EvrPYIRPWah9cA6dtxARx6us8EytrNIDv7UVGXw/cQEPR1nZamz6HROqT4Fpwfc=
Just add -decrypt argument for openssl
node test.js | openssl base64 -d -A | openssl rsautl -decrypt -oaep -inkey id_rsa
works pretty nice for me.
When using openssl to encrypt/decrypt data and the AES cipher, my command will look something like this:
openssl enc -aes-256-cbc -in message_file -K 42AB7FCE7BFEEE03E16719044916CBD475F6D000F230D213FF0F4775EF8D46F5 -iv D5C21AC249B26A1FBA376E8CFCDC4E1A -S 2C6A1B8EAACA302D -e -out message_file.enc
This places the key, iv, and salt in my process title that is visible in top/ps. Is there a way to AES encrypt a file with openssl (or even another alternative if not) without revealing this information? I did not see an option to grab these strings from files.
RSA encryption:
http://bsdsupport.org/q-how-do-i-use-openssl-to-encrypt-files/
openssl rsautl -encrypt -pubin -inkey public.key -in plaintext.txt -out encrypted.txt
AES encryption:
Based on the results of openssl enc -h
openssl enc -aes-128-cbc -in foo -out foo.enc -kfile passwordfile
And here's the result of openssl enc -h. Note the description of -kfile
root#bt:/tmp# openssl enc -h
unknown option '-h'
options are
-in <file> input file
-out <file> output file
-pass <arg> pass phrase source
-e encrypt
-d decrypt
-a/-base64 base64 encode/decode, depending on encryption flag
-k passphrase is the next argument
-kfile passphrase is the first line of the file argument
-md the next argument is the md to use to create a key
from a passphrase. One of md2, md5, sha or sha1
-K/-iv key/iv in hex is the next argument
-[pP] print the iv/key (then exit if -P)
-bufsize <n> buffer size
-engine e use engine e, possibly a hardware device.
Cipher Types
-aes-128-cbc -aes-128-cfb -aes-128-cfb1
-aes-128-cfb8 -aes-128-ecb -aes-128-ofb
-aes-192-cbc -aes-192-cfb -aes-192-cfb1
-aes-192-cfb8 -aes-192-ecb -aes-192-ofb
-aes-256-cbc -aes-256-cfb -aes-256-cfb1
-aes-256-cfb8 -aes-256-ecb -aes-256-ofb
-aes128 -aes192 -aes256
-bf -bf-cbc -bf-cfb
-bf-ecb -bf-ofb -blowfish
-cast -cast-cbc -cast5-cbc
-cast5-cfb -cast5-ecb -cast5-ofb
-des -des-cbc -des-cfb
-des-cfb1 -des-cfb8 -des-ecb
-des-ede -des-ede-cbc -des-ede-cfb
-des-ede-ofb -des-ede3 -des-ede3-cbc
-des-ede3-cfb -des-ede3-ofb -des-ofb
-des3 -desx -desx-cbc
-rc2 -rc2-40-cbc -rc2-64-cbc
-rc2-cbc -rc2-cfb -rc2-ecb
-rc2-ofb -rc4 -rc4-40
openssl can take commands from stdin
For example if onetime_keyfile specifies the key and IV with the following contents
-K 42AB7FCE7BFEEE03E16719044916CBD475F6D000F230D213FF0F4775EF8D46F5 -iv D5C21AC249B26A1FBA376E8CFCDC4E1A
Then the following commands will encrypt a file using that information
umask 077
echo -n "enc -aes-256-cbc -in message_file -out message_file.enc " > encrypt_command_file
cat onetime_keyfile >> encrypt_command_file
openssl < encrypt_command_file
Note that in your question you specify both key, initialization vector and salt. The salt argument is ignored in that case; salt is only used to derive key and iv from a pass phrase. If you specify key and iv explicitly, then you should use your own salt algorithm to generate a unique key and iv for each file that you encrypt. So in practical use, the file onetime_keyfile in the example above should be generated as output from another program.
Refer to https://www.openssl.org/docs/crypto/EVP_BytesToKey.html for details of the standard algorithm for generating key and IV from pass phrase and salt.
If you are not doing your own salting, you are probably better to use the -kfile or -pass option to read a pass phrase from a file.
I have a 16 byte character that I would like to encrypt using openssl into a 16 byte encrypted string.
This encrypted string ( in human readable format ) then needs to be supplied to a user who would use it, and the string would be decrypted to its original 16-byte form for comparison and authentication. Could anyone please tell me how this would be possible with openssl commandline.
Here's one way to encrypt a string with openssl on the command line (must enter password twice):
echo -n "aaaabbbbccccdddd" | openssl enc -e -aes-256-cbc -a -salt
enter aes-256-cbc encryption password:
Verifying - enter aes-256-cbc encryption password:
Here's what the output looks like:
U2FsdGVkX1/6LATntslD80T2HEIn3A0BqxarNfwbg31D2kI00dYbmBo8Mqt42PIm
Edit: To my knowledge, you can't control the number of bytes out. You can b64 or hex encode it, but that's about it. Also, if you want to save that string to a file rather than stdout, use the -out option.
Try this:
echo 'foo' | openssl aes-256-cbc -a -salt
echo 'U2FsdGVkX1/QGdl4syQE8bLFSr2HzoAlcG299U/T/Xk=' | openssl aes-256-cbc -a -d -salt
Run
openssl list-cipher-commands
to list all available ciphers.
I have a 16 byte character that I would like to encrypt using openssl into a 16 byte encrypted string [in human readable format]
I believe you are looking for Format Preserving Encryption. I think the caveat is you have to start with a 16-byte human readable string. Phillip Rogaway has a paper on the technologies: Synopsis of
Format-Preserving Encryption. There's a lot to the paper, and it can't fit into a single paragraph on Stack Overflow.
If you can start with a shorter string and use a streaming mode like OCB, OFB or CTR, then you can Base64 encode the final string so that the result is 16-bytes and human readable. Base64 expands at a rate of 3 → 4 (3 un-encoded expands to 4 encoded), so you'd need a shorter string of length 12 characters to achieve 16 human readable characters.
As far as I know, there are no command line tools that do it natively. You may be able to use OpenSSL on the command line with AES/CTR and pipe it through base64 command. The following gets close, but it starts with 11 characters (and not 12):
$ echo 12345678901 | openssl enc -e -base64 -aes-128-ctr -nopad -nosalt -k secret_password
cSTzU8+UPQQwpRAq
Also, you really need to understand te -k option (and -K for that matter), and how it derives a key so you can do it outside of the OpenSSL command (if needed).
try this
$ echo "a_byte_character" | openssl enc -base64
and you have 100+ Cipher Types
-aes-128-cbc -aes-128-cfb -aes-128-cfb1
-aes-128-cfb8 -aes-128-ctr -aes-128-ecb
-aes-128-gcm -aes-128-ofb -aes-128-xts
-aes-192-cbc -aes-192-cfb -aes-192-cfb1
-aes-192-cfb8 -aes-192-ctr -aes-192-ecb
-aes-192-gcm -aes-192-ofb -aes-256-cbc
-aes-256-cfb -aes-256-cfb1 -aes-256-cfb8
-aes-256-ctr -aes-256-ecb -aes-256-gcm
-aes-256-ofb -aes-256-xts -aes128
-aes192 -aes256 -bf
-bf-cbc -bf-cfb -bf-ecb
-bf-ofb -blowfish -camellia-128-cbc
-camellia-128-cfb -camellia-128-cfb1 -camellia-128-cfb8
-camellia-128-ecb -camellia-128-ofb -camellia-192-cbc
-camellia-192-cfb -camellia-192-cfb1 -camellia-192-cfb8
-camellia-192-ecb -camellia-192-ofb -camellia-256-cbc
-camellia-256-cfb -camellia-256-cfb1 -camellia-256-cfb8
-camellia-256-ecb -camellia-256-ofb -camellia128
-camellia192 -camellia256 -cast
-cast-cbc -cast5-cbc -cast5-cfb
-cast5-ecb -cast5-ofb -des
-des-cbc -des-cfb -des-cfb1
-des-cfb8 -des-ecb -des-ede
-des-ede-cbc -des-ede-cfb -des-ede-ofb
-des-ede3 -des-ede3-cbc -des-ede3-cfb
-des-ede3-cfb1 -des-ede3-cfb8 -des-ede3-ofb
-des-ofb -des3 -desx
-desx-cbc -id-aes128-GCM -id-aes192-GCM
-id-aes256-GCM -rc2 -rc2-40-cbc
-rc2-64-cbc -rc2-cbc -rc2-cfb
-rc2-ecb -rc2-ofb -rc4
-rc4-40 -rc4-hmac-md5 -seed
-seed-cbc -seed-cfb -seed-ecb
-seed-ofb
I had trouble getting it working using echo with -n. This worked for me:
To encrypt:
echo "PLAINTEXT_STRING" | openssl enc -aes256 -pbkdf2 -base64
you'll be prompted to provide a decryption password.
To decrypt:
echo "ENCRYPTED_STRING" | openssl aes-256-cbc -d -pbkdf2 -a
enter the decryption password to decrypt.