Constants
BigInt256 = BigInt.new(255)
CURVE_ORDER = (Two ** (BigInt.new(252))) + (BigInt.new("27742317777372353535851937790883648493"))
D_MINUS_ONE_SQ = BigInt.new("40440834346308536858101042469323190826248399146238708352240133220865137265952")
Hexes = (0..255).each.with_index.map do |v, i| (i.to_s(16)).rjust(2, '0') end.to_a
Convert between types
INVSQRT_A_MINUS_D = BigInt.new("54469307008909316920995813868745141605393597292927456921205312896311721017578")
MAX_256B = Noble::Ed25519::Two ** (BigInt.new(256))
ONE_MINUS_D_SQ = BigInt.new("1159843021668779879193775521855586647937357759715417654439879720876111806838")
PointPrecomputes = Hash(Point, Array(ExtendedPoint)).new()
Stores precomputed values for points.
SQRT_AD_MINUS_ONE = BigInt.new("25063068953384623474111414158702152701244531502492656460079210482610430750235")
SQRT_D = BigInt.new("6853475219497561581579357271197624642482790079785650197046958215289687604742")
SQRT_M1 = BigInt.new("19681161376707505956807079304988542015446066515923890162744021073123829784752")
√(-1) aka √(a) aka 2^((p-1)/4)
Instance methods
adjustBytes25519(bytes : Bytes) : Bytes
Sourcebytes255ToNumberLE(bytes : Bytes) : BigInt
SourcebytesToHex(uint8a : Bytes) : String
SourcebytesToNumberLE(uint8a : Bytes) : BigInt
SourceconcatBytes(*arrays) : Bytes
Sourcecswap(swap : BigInt, x_2 : BigInt, x_3 : BigInt) : Tuple(BigInt, BigInt)
SourcedecodeScalar25519(n : Hex) : BigInt
SourcedecodeUCoordinate(uEnc : Hex) : BigInt
SourceedIsNegative(num : BigInt)
Little-endian check for first LE bit (last BE bit)
SourceencodeUCoordinate(u : BigInt) : Bytes
SourceensureBytes(hex : Hex, expectedLength : Int32 | Nil = nil) : Bytes
SourceequalBytes(b1 : Bytes, b2 : Bytes)
SourcegetExtendedPublicKey(key : PrivKey)
Private convenience method
RFC8032 5.1.5
SourcegetPublicKey(privateKey : PrivKey) : Bytes
**
Calculates ed25519 public key.
- private key is hashed with sha512, then first 32 bytes are taken from the hash
- 3 least significant bits of the first byte are cleared
RFC8032 5.1.5
/
SourcegetSharedSecret(privateKey : PrivKey, publicKey : Hex) : Bytes
**
Calculates X25519 DH shared secret from ed25519 private & public keys.
Curve25519 used in X25519 consumes private keys as-is, while ed25519 hashes them with sha512.
Which means we will need to normalize ed25519 seeds to "hashed repr".
@param privateKey ed25519 private key
@param publicKey ed25519 public key
@returns X25519 shared key
/
SourcehexToBytes(hex : String) : Bytes
Caching slows it down 2-3x
Sourceinvert(number : BigInt, modulo : BigInt = Curve::P) : BigInt
Note: this egcd-based invert is 50% faster than powMod-based one.
Inverses number over modulo
SourceinvertBatch(nums : Array(BigInt), p : BigInt = Curve::P) : Array(BigInt)
**
Takes a list of numbers, efficiently inverts all of them.
@param nums list of BigInts
@param p modulo
@returns list of inverted BigInts
@example
Noble::Ed25519.invertBatch([1n, 2n, 4n], 21n)
=> [1n, 11n, 16n]
/
SourceinvertSqrt(number : BigInt)
Sourcemod(a : BigInt, b : BigInt = Curve::P) : BigInt
SourcemontgomeryLadder(pointU : BigInt, scalar : BigInt) : BigInt
x25519 from 4
**
@param pointU u coordinate (x) on Montgomery Curve 25519
@param scalar by which the point would be multiplied
@returns new Point on Montgomery curve
/
SourcenumberTo32BytesBE(num : BigInt) : Bytes
SourcenumberTo32BytesLE(num : BigInt) : Bytes
Sourcepow2(x : BigInt, power : BigInt) : BigInt
Does x ^ (2 ^ power) mod p. pow2(30, 4) == 30 ^ (2 ^ 4)
Sourcepow_2_252_3(x : BigInt)
Power to (p-5)/8 aka x^(2^252-3)
Used to calculate y - the square root of y².
Exponentiates it to very big number.
We are unwrapping the loop because it's 2x faster.
(2n**252n-3n).toString(2) would produce bits [250x 1, 0, 1]
We are multiplying it bit-by-bit
Sourcesha512ModqLE(*args) : BigInt
Little-endian SHA512 with modulo n
Sourcesign(message : Hex, privateKey : Hex) : Bytes
**
Signs message with privateKey.
RFC8032 5.1.6
/
SourceuvRatio(u : BigInt, v : BigInt) : NamedTuple(isValid: Bool, value: BigInt)
Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3.
Constant-time
prettier-ignore
Sourceverify(sig : SigType, message : Hex, publicKey : PubKey) : Bool
**
Verifies ed25519 signature against message and public key.
An extended group equation is checked.
RFC8032 5.1.7
Compliant with ZIP215:
0 <= sig.R/publicKey < 2**256 (can be >= curve.P)
0 <= sig.s < l
Not compliant with RFC8032: it's not possible to comply to both ZIP & RFC at the same time.
/
Source