Browse the docs

silk.crypto.ed25519.

Ed25519 signature verification for 32-byte public keys and 64-byte signatures (RFC 8032).

When to use#

Use Ed25519PublicKey to check that a message was signed by the holder of a known Ed25519 key, such as a release signing key. This module verifies only; it cannot sign.

Details#

fromBytes decodes and checks the public key once. verify borrows the message and the signature, requires the scalar half of the signature to be below the group order, and checks the cofactorless equation [S]B = R + [k]A with k = SHA-512(R || A || M) mod L. Arithmetic uses bounded local storage, without an allocator.

Gotchas#

Verification works on public data and does not try to run in constant time. A valid signature proves only that the key holder signed these exact bytes. For prehashed formats, such as minisign's ED algorithm, pass the digest as the message.

Examples#

Reject a signature over a different message#

silk
import silk.crypto.ed25519 {Ed25519PublicKey}
import silk.core.result {Result}

pub fn main() -> i32 {
  // RFC 8032 section 7.1, test 1: the empty message.
  let key: [u8; 32] = [
    215, 90, 152, 1, 130, 177, 10, 183, 213, 75, 254, 211, 201, 100, 7, 58,
    14, 225, 114, 243, 218, 166, 35, 37, 175, 2, 26, 104, 247, 7, 81, 26,
  ]
  let signature: [u8; 64] = [
    229, 86, 67, 0, 195, 96, 172, 114, 144, 134, 226, 204, 128, 110, 130, 138,
    132, 135, 127, 30, 184, 229, 217, 116, 216, 115, 224, 101, 34, 73, 1, 85,
    95, 184, 130, 21, 144, 163, 59, 172, 198, 30, 57, 112, 28, 249, 180, 107,
    210, 91, 245, 240, 89, 91, 190, 36, 101, 81, 65, 67, 142, 122, 16, 11,
  ]
  let empty: [u8; 0] = []
  let other: [u8; 1] = [0]
  return match Ed25519PublicKey.fromBytes(&key) {
    Result.Failure { error } => 1
    Result.Success { value: verifier } => {
      let accepted = match verifier.verify(&empty, &signature) {
        Result.Success { value } => true
        Result.Failure { error } => false
      }
      let forged = match verifier.verify(&other, &signature) {
        Result.Success { value } => true
        Result.Failure { error } => false
      }
      if !accepted || forged {
        return 2
      }
      return 0
    }
  }
}

Import as Ed25519PublicKey with import silk.crypto.ed25519 { Ed25519PublicKey }.

Public declarations: 2.

Ed25519Error#

silk
pub enum Ed25519Error

A rejected Ed25519 input, without the input bytes in the error.

InvalidKeyLength#

silk
InvalidKeyLength

A public key encoding whose length is not 32 bytes.

InvalidKey#

silk
InvalidKey

A public key that does not encode a point on the curve.

InvalidSignatureLength#

silk
InvalidSignatureLength

A signature whose length is not 64 bytes.

InvalidSignature#

silk
InvalidSignature

A signature that does not verify for this key and message.

Implementation Debug for Ed25519Error#

silk
impl Debug for Ed25519Error

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut Writer

Writes the name of the variant, such as InvalidKeyLength.

Ed25519PublicKey#

silk
pub struct Ed25519PublicKey

A decoded Ed25519 public key, for signature verification only (RFC 8032).

When to use#

Use it to check that a message was signed by the holder of a known Ed25519 key, such as a release signing key. Decode the key once with Ed25519PublicKey.fromBytes, then call Ed25519PublicKey.verify. It cannot sign.

Gotchas#

Verification works on public data and does not try to run in constant time. A valid signature proves only that the key holder signed these exact bytes. For prehashed formats, such as minisign's ED algorithm, pass the digest as the message.

Implementation Ed25519PublicKey#

silk
impl Ed25519PublicKey

Associated function fromBytes#

silk
pub fn fromBytes(bytes: &[u8]) -> Result<Ed25519PublicKey, Ed25519Error>

Decodes exactly 32 borrowed public key bytes.

Errors#

InvalidKeyLength when bytes is not 32 bytes long, and InvalidKey when it does not encode a curve point.

Method bytes#

silk
pub fn bytes(self: &Ed25519PublicKey) -> [u8; 32]

Returns the 32-byte encoding this key was decoded from.

Method verify#

silk
pub fn verify(self: &Ed25519PublicKey, message: &[u8], signature: &[u8]) -> Result<
    (),
    Ed25519Error
  >

Checks that signature is this key's Ed25519 signature of message.

It borrows the message and the signature, requires the scalar half of the signature to be below the group order, and checks the cofactorless equation [S]B = R + [k]A with k = SHA-512(R || A || M) mod L. It does not allocate.

Gotchas#

It does not try to run in constant time. A valid signature proves only that the key holder signed these exact bytes. For prehashed formats, such as minisign's ED algorithm, pass the digest as the message.

Errors#

InvalidSignatureLength when signature is not 64 bytes long, and InvalidSignature when its scalar is not below the group order or the verification equation does not hold.

Category: Cryptography.

Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2.

View the source of this page