x25519.rb

An efficient public key cryptography library for Ruby providing key exchange/agreement.
This gem implements X25519 (a.k.a. Curve25519) Elliptic Curve Diffie-Hellman function as described in RFC7748 as a C extension using the high performance rfc7748_precomputed implementation based on the paper How to (pre-)compute a ladder.
X25519 is one of two notable algorithms implemented atop the Curve25519 elliptic curve. The ed25519 gem is a related project of this one, and implements the Ed25519 signature scheme on the twisted Edwards form of Curve25519.
Requirements
x25519.rb is supported on and tested against the following platforms:
- MRI 2.2, 2.3, 2.4, 2.5
Installation
Add this line to your application's Gemfile:
gem "x25519"
And then execute:
$ bundle
Or install it yourself as:
$ gem install x25519
Usage
The example below shows how to perform a full Diffie-Hellman key exchange:
require "x25519"
# Alice generates random scalar (private key)
alice_sk = X25519::Scalar.generate
# Alice obtains public key for her private key/scalar
alice_pk = alice_sk.public_key
# Bob generates random scalar (private key)
# Ostensibly this would be on a different computer somewhere
bob_sk = X25519::Scalar.generate
bob_pk = bob_sk.public_key
# Alice can perform Diffie-Hellman with Bob's public key
alice_secret = alice_sk.diffie_hellman(bob_pk).to_bytes
# Bob can perform Diffie-Hellman with Alice's public key
bob_secret = bob_sk.diffie_hellman(alice_pk).to_bytes
# The resulting secrets should be the same
alice_secret == bob_secret # true
X25519::Scalar: private keys
The X25519::Scalar
class represents secret integers used as X25519 private
keys. These secret integers are multiplied by a well-known base point to
obtain X25519 public keys (X25519::MontgomeryU
).
X25519::Scalar.generate()
: make a random private key
Generate a random private scalar (using SecureRandom
)
Example:
secret_key = X25519::Scalar.generate
X25519::Scalar.new(bytes)
: load existing private key
bytes
: a 32-byteString
value containing the private key
Example:
secret_key = X25519::Scalar.new(File.read("alice.key"))
X25519::Scalar#public_key()
: obtain public key for this scalar
NOTE: The #multiply_base
method is an alias of this one.
Performs fixed-base scalar multiplication (i.e. calculates public key)
Return Value:
Returns a X25519::MontgomeryU
object which represents the public key for this private key/scalar.
Example:
secret_key = X25519::Scalar.generate
public_key = secret_key.public_key
X25519::Scalar#diffie_hellman(other_public_key)
: obtain public key for this scalar
NOTE: The #multiply
method is an alias of this one.
Performs variable-base scalar multiplication, computing a shared secret between our private scalar and someone else's public key/point.
Arguments:
other_public_key
: aX25519::MontgomeryU
object containing the public key with which we'd like to compute a shared secret.
Return Value:
Returns a X25519::MontgomeryU
object which represents the shared secret.
Example:
secret_key = X25519::Scalar.generate
public_key = X25519::MontgomeryU.new(File.read("bob.pub"))
# Returns an X25519::MontgomeryU
shared_secret = secret_key.multiply(public_key)
# Obtain the shared secret as a serialized byte representation
shared_secret_bytes = shared_secret.to_bytes
X25519::Scalar#to_bytes
: serialize a scalar as a String
Return Value:
Returns a String
containing a byte representation of this scalar:
Example:
secret_key = X25519::Scalar.new(...)
File.write("alice.key", secret_key.to_bytes)
X25519::MontgomeryU: public keys and shared secrets
The X25519::MontgomeryU
class represents a coordinate (specifically a
Montgomery-u coordinate) on the elliptic curve. In the X25519 Diffie-Hellman
function, these serve both as public keys and as shared secrets.
X25519::MontgomeryU.new(bytes)
: load existing public key
Arguments:
bytes
: a 32-byteString
value containing the public key
Example:
public_key = X25519::MontgomeryU.new(File.read("bob.pub"))
X25519::MontgomeryU#to_bytes
: serialize a Montgomery-u coordinate as a String
Return Value:
Returns a String
containing a byte representation of a compressed Montgomery-u coordinate:
Example:
public_key = X25519::MontgomeryU..new(...)
File.write("bob.pub", public_key.to_bytes)
X25519: module-level functionality
X25519.diffie_hellman(secret_key, public_key)
: shorthand String
-oriented API
If you'd like to avoid the object-oriented API, you can use a simplified API which acts entirely on bytestrings.
Arguments:
secret_key
: a 32-byteString
containing a private scalarpublic_key
: a 32-byteString
containing a compressed Montgomery-u coordinate
Return Value:
Returns a String
containing a 32-byte compressed Montgomery-u coordinate
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/crypto-rb/x25519. This project is intended to be a safe, welcoming space for collaboration, and contributors areexpected to adhere to the Contributor Covenant code of conduct.
Implementation Details
This gem contains two implementations of X25519: an optimized assembly implementation and a portable C implementation. Implementations are selected based on available CPU features.
rfc7748_precomputed: optimized assembly implementation
- Prime field arithmetic is optimized for the 4th and 6th generation of Intel Core processors (Haswell and Skylake micro-architectures).
- Efficient integer multiplication using MULX instruction.
- Integer additions accelerated with ADCX/ADOX instructions.
- Key generation uses a read-only table of 8 KB for X25519.
ref10: portable C implementation
- Taken from the SUPERCOP cryptographic benchmarking suite (supercop-20171020)
- Portable C code which should compile on any architecture
Designers
The X25519 Diffie-Hellman function was originally designed by Dan Bernstein:
The optimized rfc7748_precomputed implementation was designed by:
- Thomaz Oliveira, Computer Science Department, Cinvestav-IPN, Mexico.
- Julio López, University of Campinas, Brazil.
- Hüseyin Hisil, Yasar University, Turkey.
- Armando Faz-Hernández, University of Campinas, Brazil.
- Francisco Rodríguez-Henríquez, Computer Science Department, Cinvestav-IPN, Mexico.
Copyright and License
Copyright (c) 2017-2018 Armando Faz, Tony Arcieri
This gem is available as open source under the terms of the GNU Lesser General Public License v3.0 (LICENSE)
Code of Conduct
Everyone interacting in the x25519.rb project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.