Symmetrical vs asymmetrical crypto
Disclaimer: This content is merely educational. Don't roll your own crypto. Use TLS and GPG.
These aren't new topics, but if you're reading this maybe you could use a quick reminder (or intro if you aren't familiar).
We're taking a look at the differences between symmetrical and asymmetrical cryptographic operations.
The operations themselves can be:
Creating additional content — called a signature — based on a message that proves it's author had access to a specific key.
A certain signature for a certain content can only be produced with a certain key, and this must be verifiable.
The signature should be provided along with the message, both parts are needed to verify authorship.
Signing a message doesn't prevent anyone else from reading it, it only prevents someone without access to the key from tampering or forging the message.
A signature's size shouldn't vary with the size of the message.
It is not possible to obtain the message from a signature.
Modifying a message so that it becomes unreadable for anyone without access to a specific key.
Sending an encrypted message may prevent people without access to the decrypting key from reading it, but it does not prevent tampering or forging of messages.
Symmetrical means there's a shared key. It means the same key used to encrypt is used to decrypt, and it means that the same key used to produce a signature is also the key necessary to verify the signature.
Symmetrical encryption has been around for a long time. It can be as simple as shifting letters/digits by a number determined by the key.
Example in node
var crypto = require('crypto'); var message = 'original message'; var key = 'secret'; var cipherAlgorithm = 'aes-256-cbc'; var clearTextEncoding = 'utf8'; var cipherTextEncoding = 'base64'; var cipher = crypto.createCipher(cipherAlgorithm, key); var ciphered; ciphered += cipher.update(message, clearTextEncoding, cipherTextEncoding); ciphered += cipher.final(cipherTextEncoding); console.log('Ciphered:', ciphered); var decipher = crypto.createDecipher(cipherAlgorithm, key); var deciphered; deciphered += decipher.update(ciphered, cipherTextEncoding, clearTextEncoding); deciphered += decipher.final(clearTextEncoding); console.log('Deciphered:', deciphered);
Instead of 'signature' the term MAC (Message Authentication Code) is more frequently used. MAC is frequently used to describe both the signature as well as the algorithm that produced it.
Most MAC algorithms are based on hashing functions, and the most common way they work is by producing a hash of the content mixed with the key.
If the hashing function is any good, it won't be feasible to forge or tamper a message and produce the correct MAC without the key.
A MAC algorithm can be as simple as using a good hash function, and applying it to the content mixed with the key.
A very popular MAC algorithm is the HMAC.
Example in node
var crypto = require('crypto'); var message = 'original message'; var key = 'secret'; var hashAlgorithm = 'sha256'; var macEncoding = 'base64'; var hmac = crypto.createHmac(hashAlgorithm, key); hmac.update(message); var mac = hmac.digest(macEncoding); console.log('Mac:', mac);
Asymmetrical means each party has two keys, a public and a private one. A public key can be derived from the private one, but the reverse operation isn't possible.
Asymmetrical operations are many times much slower than symmetrical operations. So why and when should you use them?
Symmetrical operations require a common key for both parties
Both keys needs to be used in a transaction:
- Alice signs a document with her private key and anyone can verify that she did using her public key.
- To send a secret message to Alice, we encrypt it with Alice's public key, only her private key is able to decrypt it.
Notice the different key uses:
- Public key
- Verifying signatures
- Private key
Asymmetrical encryption is very recent, the first practical algorithm, RSA, was published in 1977.
$ cat message HELLO THERE $ gpg --encrypt --armor --recipient email@example.com < message > encrypted $ cat encrypted -----BEGIN PGP MESSAGE----- Version: GnuPG/MacGPG2 v2.0.22 (Darwin) Comment: GPGTools - https://gpgtools.org hQEMA7AQgA7KfpdAAQf8CWm1F0P+nd3xChVGMfWUKlIL2nBQsEHSv4wrMJatQmqE 8PWkX+X1T7wBlR2aILItCPH7M+N0m+1ePDK/2wkyxtQKnIXVSGk+v0LJDxf6PoZD 3mhMj9ntCGL+orWKlonvRgMepxEmFbNd1JLaX30LAkmjr+fYPcpseIAKjDVgB+JX qXxrQvOxwzWdbewq0/LO/tTJL9FUn9g30ja8GCf5QDL+rc6ksFPWlzbDItVRSHqT SyaL5HGiRyONH9KW3Exv+0vVZ+R2oLqzU4/WMYjuFJ7Eqv7wz0p7vxceT57VOPIF NrzEXQ/Ci7BhyWkuWJo6wBdBwIta9PyyPJY73taEBtJHAb9mJcR0aFPgex4HfrRM GSuTBOJVGyEFFcUwUjP3yY2Ck7WbTsLQkfZh4t+zP3Lw31oXLqpP5BaSMJ2tYnZG fS2sEK1lldQ= =/xtk -----END PGP MESSAGE----- $ gpg --decrypt You need a passphrase to unlock the secret key for user: "Igor Soarez <firstname.lastname@example.org>" 2048-bit RSA key, ID CA7E9740, created 2014-03-26 (main key ID 1C1987ED) gpg: encrypted with 2048-bit RSA key, ID CA7E9740, created 2014-03-26 "Igor Soarez <email@example.com>" HELLO THERE
Notice that we had to specify the recipient, this identifies which public key to use in the encryption process.
If you want to try GPG take a look at a GPG setup guide.
The way that RSA is used for signing is buy using a funny trick. The author calculates a hash of the message and decrypts it with his own private key. That's right, decrypts it. Then someone can encrypt it to get to the hash and verify that the hash is correct. The trick is that the encryption and decryption operations are used in a different way than what they were designed to. Only the owner of the private key could have produced something that when encrypted with the corresponding public key turns to a specific result.
While symmetrical crypto is enough for use within a closed group, e.g. a set of micro-services made by the same team, asymmetrical crypto is necessary when dealing with many parties who do not trust each other and maintaining a common key with each party becomes problematic.
Even when using asymmetrical cryptography a common workflow is to quickly establish a common key used for the session and switch to symmetrical cryptography because symmetrical is much faster and requires less resources.
$ gpg --sign --clearsign < message $ cat message -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 HELLO THERE -----BEGIN PGP SIGNATURE----- Version: GnuPG/MacGPG2 v2.0.22 (Darwin) Comment: GPGTools - https://gpgtools.org iQEcBAEBCgAGBQJVbYNxAAoJEOkvWAkcGYftoacH/2uj531SNKbMwlqyFk2PfsQm Tsee7x5NKYPNXj8IvcQCQWHsJHXZS5kV9tNMgwontFAUegfbi0JZsEH3JA25RRLG qqcNYHsvDFTobuTaD+qEnwq4/QT0fHtssHoyHjKJrqQgt4UsIITFAhwALh82OyfJ oTty94v7fjC+CTqtLAenD7oQMvAklL4epBLpozrSwBA2u7LPnfzMG8x6Oeyl5KjQ x4K7bVgkfffcNbCgztUUNTUGiH73zBKWFwI+dzLmIrEQjncWsSTf/JxG3R1A7SDS pv/gw4yCauv1pymeQB5gCecIrUyfHOX/CTrBTjyoPL642XwmoULWWBlwNJhTR9o= =oCct -----END PGP SIGNATURE----- $ gpg --verify signed gpg --verify signed gpg: Signature made Tue Jun 2 11:20:33 2015 BST using RSA key ID 1C1987ED gpg: Good signature from "Igor Soarez <firstname.lastname@example.org>"
If you want to try GPG take a look at a GPG setup guide.
I hope this very short intro was helpful. If you want to learn more, I recommend looking at a much more comprehensive introduction to cryptography — Journey into Cryptography by KhanAcademy.