Class: RbNaCl::Signatures::Ed25519::SigningKey

Inherits:
Object
  • Object
show all
Extended by:
RbNaCl::Sodium
Includes:
KeyComparator, RbNaCl::Serializable
Defined in:
lib/rbnacl/signatures/ed25519/signing_key.rb

Overview

Private key for producing digital signatures using the Ed25519 algorithm. Ed25519 provides a 128-bit security level, that is to say, all known attacks take at least 2^128 operations, providing the same security level as AES-128, NIST P-256, and RSA-3072.

Signing keys are produced from a 32-byte (256-bit) random seed value. This value can be passed into the SigningKey constructor as a String whose bytesize is 32.

The public VerifyKey can be computed from the private 32-byte seed value as well, eliminating the need to store a "keypair".

SigningKey produces 64-byte (512-bit) signatures. The signatures are deterministic: signing the same message will always produce the same signature. This prevents "entropy failure" seen in other signature algorithms like DSA and ECDSA, where poor random number generators can leak enough information to recover the private key.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from RbNaCl::Sodium

sodium_constant, sodium_function, sodium_function_with_return_code, sodium_primitive, sodium_type

Methods included from RbNaCl::Serializable

#inspect, #to_s, #to_str

Methods included from KeyComparator

#<=>, #==

Constructor Details

#initialize(seed) ⇒ RbNaCl::SigningKey

Create a SigningKey from a seed value

Parameters:

  • seed (String)

    Random 32-byte value (i.e. private key)



59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/rbnacl/signatures/ed25519/signing_key.rb', line 59

def initialize(seed)
  seed = seed.to_s

  Util.check_length(seed, Ed25519::SEEDBYTES, "seed")

  pk = Util.zeros(Ed25519::VERIFYKEYBYTES)
  sk = Util.zeros(Ed25519::SIGNINGKEYBYTES)

  self.class.sign_ed25519_seed_keypair(pk, sk, seed) || raise(CryptoError, "Failed to generate a key pair")

  @seed        = seed
  @signing_key = sk
  @verify_key  = VerifyKey.new(pk)
end

Instance Attribute Details

#verify_keyObject (readonly)

Returns the value of attribute verify_key.



45
46
47
# File 'lib/rbnacl/signatures/ed25519/signing_key.rb', line 45

def verify_key
  @verify_key
end

Class Method Details

.generateRbNaCl::SigningKey

Generate a random SigningKey

Returns:



50
51
52
# File 'lib/rbnacl/signatures/ed25519/signing_key.rb', line 50

def self.generate
  new RbNaCl::Random.random_bytes(Ed25519::SEEDBYTES)
end

.signature_bytesInteger

The size of signatures generated by the SigningKey class

Returns:

  • (Integer)

    The number of bytes in a signature



120
121
122
# File 'lib/rbnacl/signatures/ed25519/signing_key.rb', line 120

def self.signature_bytes
  Ed25519::SIGNATUREBYTES
end

Instance Method Details

#keypair_bytesString

Return the raw 64 byte value of this key

Returns:

  • (String)

    The signature key bytes. Left half is 32-byte curve25519 private scalar, right half is 32-byte group element



106
107
108
# File 'lib/rbnacl/signatures/ed25519/signing_key.rb', line 106

def keypair_bytes
  @signing_key
end

#primitiveSymbol

The crypto primitive this SigningKey class uses for signatures

Returns:

  • (Symbol)

    The primitive



113
114
115
# File 'lib/rbnacl/signatures/ed25519/signing_key.rb', line 113

def primitive
  self.class.primitive
end

#sign(message) ⇒ String

Sign a message using this key

Parameters:

  • message (String)

    Message to be signed by this key

Returns:

  • (String)

    Signature as bytes



79
80
81
# File 'lib/rbnacl/signatures/ed25519/signing_key.rb', line 79

def sign(message)
  sign_attached(message)[0, signature_bytes]
end

#sign_attached(message) ⇒ String

Sign a message using this key, attaching the signature to the message

Parameters:

  • message (String)

    Message to be signed by this key

Returns:

  • (String)

    Signature and the message as bytes



88
89
90
91
92
93
# File 'lib/rbnacl/signatures/ed25519/signing_key.rb', line 88

def sign_attached(message)
  buffer = Util.prepend_zeros(signature_bytes, message)
  buffer_len = Util.zeros(FFI::Type::LONG_LONG.size)
  self.class.sign_ed25519(buffer, buffer_len, message, message.bytesize, @signing_key)
  buffer
end

#signature_bytesInteger

The size of signatures generated by the SigningKey instance

Returns:

  • (Integer)

    The number of bytes in a signature



127
128
129
# File 'lib/rbnacl/signatures/ed25519/signing_key.rb', line 127

def signature_bytes
  Ed25519::SIGNATUREBYTES
end

#to_bytesString

Return the raw seed value of this key

Returns:

  • (String)

    seed used to create this key



98
99
100
# File 'lib/rbnacl/signatures/ed25519/signing_key.rb', line 98

def to_bytes
  @seed
end

#to_curve25519_private_keyRbNaCl::PrivateKey

Return a new curve25519 (x25519) private key converted from this key

it's recommeneded to read https://libsodium.gitbook.io/doc/advanced/ed25519-curve25519 as it encourages using distinct keys for signing and for encryption

Returns:



137
138
139
140
141
# File 'lib/rbnacl/signatures/ed25519/signing_key.rb', line 137

def to_curve25519_private_key
  buffer = Util.zeros(Boxes::Curve25519XSalsa20Poly1305::PrivateKey::BYTES)
  self.class.crypto_sign_ed25519_sk_to_curve25519(buffer, @signing_key)
  Boxes::Curve25519XSalsa20Poly1305::PrivateKey.new(buffer)
end