BlueECC: Encrypt, Decrypt, Sign and Verify with Elliptic Curve
By Andrew Lees
Created on 2019-03-04
We have just released BlueECC, a new Swift package for cross-platform elliptic curve cryptography. This enables you to encrypt, decrypt, sign and verify data using elliptic curve asymmetric keys. This blog post will explain what elliptic curves are, why you would use them over RSA and provides examples of the BlueECC API.
In RSA cryptography, the security of the public/private key pair relies on the complexity of factorizing a large integer. In Elliptic Curve Cryptography, the security relies on the complexity of finding the discrete logarithm of a random elliptic curve element.
BlueECC uses the Elliptic Curve Integrated Encryption Scheme (ECIES) and Elliptic Curve Digital Signature Algorithm (ECDSA) for its cryptography. Fortunately, you do not need to know the mathematics behind the algorithms to use them. They work just like RSA with a public key for encryption/verifying and a private key for decryption/signing.
Elliptic curve (EC) keys allow you to perform the same asymmetric public key cryptography as RSA keys. However, they have gained popularity due to the following advantages:
- Smaller key sizes (a 256 bit EC private key is considered equivalent to a 3072 bit RSA private key)
- Faster key generation
- Faster signing/verifying
- Smaller signatures (approximately 1/6th the size of an equivalent RSA signature)
- Smaller encryption payloads (EC adds 81 bytes per message vs 528 bytes for RSA)
Under the covers, BlueECC uses the Apple Security framework on macOS/iOS and OpenSSL on Linux. This means you can use it on both platforms without installing additional dependencies. BlueECC is available to import through Swift Package Manager or CocoaPods.
We will use the OpenSSL command line to generate our EC private and public keys.
- On macOS you can install OpenSSL using
$ brew install openssl
- Once you have installed OpenSSL, create your private key:
$ openssl ecparam -name prime256v1 -genkey -noout -out ec256priv.pem
- Using the private key, create your public key:
$ openssl ec -in ec256priv.pem -pubout -out ec256pub.pem
This will have created two files called
ec256pub.pem. Open them in a text editor and you will see EC keys for the prime256v1 curve in PEM format. These can then be passed to BlueECC to create your keys:
let ecPubKey = try ECPublicKey(key: "<publicPEM>") let ecPrivKey = try ECPrivateKey(key: "<privatePEM>")
Alternatively, you can generate the EC Keys directly using the BlueECC:
let ecPubKey = try ecPrivKey.extractPublicKey() print(ecPrivKey.pemString) print(ecPubKey.pemString)
One use of asymmetric keys is in signing data. In this case, you produce a signature by signing the data with the private key. If the signature is successfully verified using the public key, you can be sure it was produced using the private key and that the data hasn’t been changed. This ensures the authenticity and integrity of the data.
With BlueECC you sign the plaintext as follows:
let signature = try "hello world".sign(with: ecPrivKey)
This will take your message and use the private key to create an ECSignature. This struct can then be verified with the corresponding public key:
let verified = signature.verify(plaintext: "hello world", using: ecPubKey)
To produce either
false depending on whether the signature is valid for the provided plaintext and public key.
The other use of asymmetric keys is in encryption and decryption. In this case you provide the private key to the person who you want to communicate securely with and they use it to encrypt the plaintext. The message can only be decrypted using the private key.
Since asymmetric encryption can only be used on a small plaintext, BlueECC uses Elliptic Curve Integrated Encryption Scheme (ECIES). This consists of encrypting the message using AES-GCM with a symmetric key, followed by encrypting that symmetric key using Elliptic-curve Diffie–Hellman (ECDH). The encrypted symmetric key and encrypted message are both sent in an envelope. The receiver of the envelope then decrypts the symmetric key and uses that to decrypt the original message.
BlueECC handles this process for you, so encryption becomes:
let encrypted = try "Hello World".encrypt(with: ecPubKey)
This will produce the encrypted data envelope that is structured as follows:
- Ephemeral public key (65/97/133 bytes depending on curve)
- Encrypted ciphertext (length of the plaintext)
- GCM tag (16 bytes)
To decrypt this data, pass it to BlueECC with the private key:
let decrypted = try encrypted.decrypt(with: ecPrivKey) print(String(data: decryptedData, encoding: .utf8)) // "Hello World"
The encrypted data has been decrypted back to the original plaintext.
Congratulations! You have just learned how to use elliptic curve cryptography to sign, verify, encrypt and decrypt data in Swift.
If you would like to run this example, or learn more about BlueECC, check it out on GitHub.
If you would like to learn more about using the BlueECC API, visit our API reference.
Any questions or comments? Please join the Kitura community on Slack!