I’ve been playing around with Public-key cryptography or asymmetric cryptography. With revaltions from Eric Snowden on programs like PRISM, I feel that encryption is more important than ever.
Public key encryption. A message is encrypted with a recipient’s public key. The message can only be unencrypted by the holder of the private key.
Digital Signature. A message is signed with a the senders private key to generate a cryptographic hash. Using the public key, one can verify the message was indeed sent with the coresponding private key and can ensure the message has not been altered.
Keys
First, let’s generate some keys. From the private key we will also generate the public key. Remember the private and public key are mathematically linked. This is important.
Great. Now we have a key pair. We can write these keys to disk if we like.
12345678
## write the private key to disk.File.open("~/.ssh/private_key","w+")do|f|f.writeprivate_key.to_pemend# write the public key to disk.File.open("~/.ssh/public_key.pem","w+")do|f|f.writepublic_key.to_pemend
We’ll be encrypting a message with the public key. So it can only be unenctrypted by the owner of the private key.
123
## Use the public key to encrypt a message[4]pry(main)>encrypted_data=public_key.public_encrypt("Some private data is here.")=>"\x9B\f\xD2\"\x02l\x0E\xFB\x18\xFA\xA2\xCC;\x9F\xC2r\xFA\x88\x94\\\xDBZY\x964\xE3\x13i\xDB\xB5\xB4<\x8E\xEC\xB8\xAB\"a\xE1\xE0\x01\x8Cb\xEC\xAE\x86\xC0!\x18\xC8\xA9\xDEB\e^\xCCe\x11\xDC\x19\x81\xDC\x98\x1EX\x11\xD6\"bUJ\xB0B\xED\x96\x03\x9F}\xF7I\xFD\x9F\x04\x04\xF4Q\xA7H\x9C\b\xC5\a\xE1\xA4\x02kx\xF46A% \xEB\xEB: \xD1\xA2\xFF\xA4$\xBDP\x9FR\xE9\xD3\x9F\r>\x8E5\xD9\x10\xE8\x9DYd\e`\x8E\xE0\xBD\xE5\\\x02\xF6\x83\v\x15\xD4m\x03\xCDJ\x9A*\xA6\xF5S9\xD2M\x10\xD5 7\x92\xCE\xF0\xB9<\xAFe\x9A\xAE\x8E`\xADW\x93\x91;HZ\xEB\xD8\xFF\xDE\x02\x10m\x9D\xF2*\tL2\xE2`K\xC8\x0E)O\x86\xDA\xAFk4\xD0\rN\xF3%}\xEAM\x15he\xDF\x0F\xC6\xE5\xAA$\x19\x03V\xBE\x0E~\x8ELv\x9C\xC7\xB4o\xA13\xE2\xDE\xE2t!]-\xC8\x88\xAF\xE3\xD5\xFD`T\xD9\xCDs\xFF\xAE(<\xBD\xB9"
This will result in some unreadable binary data. Next we’ll decrypt this data with the private key.
123
## Use the private key to decrypt[5]pry(main)>private_key.private_decrypt(enc)=>"Some private data is here."
Nice!
The public key can encrypt but cannot decrypt the message. This enctryption only works in one direction. Only the private key can decrypt that message. You can also encrypt messages with a private key. Those messages can be unenctrypted with the public key and the private key.
Asymmetric public/private key encryption is slow and victim to attack in cases where it is used without padding or directly to encrypt larger chunks of data. Typical use cases for RSA encryption involve “wrapping” a symmetric key with the public key of the recipient who would “unwrap” that symmetric key again using their private key.
NOTE - The enctrypted messages are in binary format. If we want to encode the data for transmission accoss the net, we’ll want to use something like base64.
This works for small messages but if you try and encrpt a string larget than your key… you’ll hit an errors. You could break up the string into smaller chunks and encrypt each chunk individually. But this is not secure. This is what cypher block chaining is for. Below is an example.
Asymmetric digital signatures is a great way to verify integrity and authenticity of data. Create a keypair, send the public key to your receivers, and use this method to create a digital signature. By combining the data and the public key, you can verify that the signature was created by the owner of the private key.
1234567891011121314151617
require"openssl"data="A small brown fox."digest=OpenSSL::Digest::SHA256.new# To list available digests:#OpenSSL::Digest.constantssignature=private_key.sign(digest,data)public_key.verify(digest,signature,data)# => truepublic_key.verify(digest,signature,data+"altered")# => falsepublic_key.verify(digest,"altered"+signature,data)# => false
More
Using openssl library directly we can encrypt a file.
1
openssl aes-256-cbc -a -e -in source-file.txt -out enc-file.txt -k private_key
And to decrypt the file.
1
openssl aes-256-cbc -d -a -in enc-file.txt -out unenc-file.txt -k private_key