Amarula.Protocol.Crypto.XEdDSA (amarula v0.1.0)

View Source

XEd25519 signatures over Curve25519 (X25519) keys, compatible with libsignal's curve25519_sign / curve25519_verify — what Baileys calls Curve.sign / Curve.verify.

WhatsApp signs the signed pre-key, the device signature (pairing) and verifies the account signature with this scheme, NOT plain Ed25519:

  • Keys are X25519 (Montgomery) keypairs; the same key does DH and signing.
  • sign: derive the Edwards public key A = a*B from the Montgomery private scalar, produce a standard Ed25519 signature with a randomized nonce, then store the sign bit of A in the top bit of the last signature byte (libsignal sign_modified.c).
  • verify: convert the Montgomery public key to an Edwards key using the sign bit carried in the signature, clear that bit, then run standard Ed25519 verification.

Summary

Functions

Convert a Montgomery u-coordinate public key to an Ed25519 public key: y = (u - 1) / (u + 1) mod p, with the given sign bit (0 or 0x80) placed in the top bit of the last byte. Returns :error when u = -1 (no inverse).

Sign message with a 32-byte X25519 private key. Returns a 64-byte signature verifiable by libsignal's curve25519_verify against the Montgomery public key.

Verify a 64-byte XEd25519 signature over message against a 32-byte Montgomery (X25519) public key.

Functions

montgomery_to_edwards(arg, sign_bit)

@spec montgomery_to_edwards(binary(), 0 | 128) :: {:ok, binary()} | :error

Convert a Montgomery u-coordinate public key to an Ed25519 public key: y = (u - 1) / (u + 1) mod p, with the given sign bit (0 or 0x80) placed in the top bit of the last byte. Returns :error when u = -1 (no inverse).

sign(message, arg)

@spec sign(binary(), binary()) :: binary()

Sign message with a 32-byte X25519 private key. Returns a 64-byte signature verifiable by libsignal's curve25519_verify against the Montgomery public key.

verify(message, arg2, arg3)

@spec verify(binary(), binary(), binary()) :: boolean()

Verify a 64-byte XEd25519 signature over message against a 32-byte Montgomery (X25519) public key.