struct Curve25519 [src]

Alias for std.crypto.25519.curve25519.Curve25519

Group operations over Curve25519.

Fields

x: Fe

Members

Source

pub const Curve25519 = struct { /// The underlying prime field. pub const Fe = @import("field.zig").Fe; /// Field arithmetic mod the order of the main subgroup. pub const scalar = @import("scalar.zig"); x: Fe, /// Decode a Curve25519 point from its compressed (X) coordinates. pub inline fn fromBytes(s: [32]u8) Curve25519 { return .{ .x = Fe.fromBytes(s) }; } /// Encode a Curve25519 point. pub inline fn toBytes(p: Curve25519) [32]u8 { return p.x.toBytes(); } /// The Curve25519 base point. pub const basePoint = Curve25519{ .x = Fe.curve25519BasePoint }; /// Check that the encoding of a Curve25519 point is canonical. pub fn rejectNonCanonical(s: [32]u8) NonCanonicalError!void { return Fe.rejectNonCanonical(s, false); } /// Reject the neutral element. pub fn rejectIdentity(p: Curve25519) IdentityElementError!void { if (p.x.isZero()) { return error.IdentityElement; } } /// Multiply a point by the cofactor, returning WeakPublicKey if the element is in a small-order group. pub fn clearCofactor(p: Curve25519) WeakPublicKeyError!Curve25519 { const cofactor = [_]u8{8} ++ [_]u8{0} ** 31; return ladder(p, cofactor, 4) catch return error.WeakPublicKey; } fn ladder(p: Curve25519, s: [32]u8, comptime bits: usize) IdentityElementError!Curve25519 { var x1 = p.x; var x2 = Fe.one; var z2 = Fe.zero; var x3 = x1; var z3 = Fe.one; var swap: u8 = 0; var pos: usize = bits - 1; while (true) : (pos -= 1) { const bit = (s[pos >> 3] >> @as(u3, @truncate(pos))) & 1; swap ^= bit; Fe.cSwap2(&x2, &x3, &z2, &z3, swap); swap = bit; const a = x2.add(z2); const b = x2.sub(z2); const aa = a.sq(); const bb = b.sq(); x2 = aa.mul(bb); const e = aa.sub(bb); const da = x3.sub(z3).mul(a); const cb = x3.add(z3).mul(b); x3 = da.add(cb).sq(); z3 = x1.mul(da.sub(cb).sq()); z2 = e.mul(bb.add(e.mul32(121666))); if (pos == 0) break; } Fe.cSwap2(&x2, &x3, &z2, &z3, swap); z2 = z2.invert(); x2 = x2.mul(z2); if (x2.isZero()) { return error.IdentityElement; } return Curve25519{ .x = x2 }; } /// Multiply a Curve25519 point by a scalar after "clamping" it. /// Clamping forces the scalar to be a multiple of the cofactor in /// order to prevent small subgroups attacks. This is the standard /// way to use Curve25519 for a DH operation. /// Return error.IdentityElement if the resulting point is /// the identity element. pub fn clampedMul(p: Curve25519, s: [32]u8) IdentityElementError!Curve25519 { var t: [32]u8 = s; scalar.clamp(&t); return try ladder(p, t, 255); } /// Multiply a Curve25519 point by a scalar without clamping it. /// Return error.IdentityElement if the resulting point is /// the identity element or error.WeakPublicKey if the public /// key is a low-order point. pub fn mul(p: Curve25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Curve25519 { _ = try p.clearCofactor(); return try ladder(p, s, 256); } /// Compute the Curve25519 equivalent to an Edwards25519 point. /// /// Note that the function doesn't check that the input point is /// on the prime order group, e.g. that it is an Ed25519 public key /// for which an Ed25519 secret key exists. /// /// If this is required, for example for compatibility with libsodium's strict /// validation policy, the caller can call the `rejectUnexpectedSubgroup` function /// on the input point before calling this function. pub fn fromEdwards25519(p: crypto.ecc.Edwards25519) IdentityElementError!Curve25519 { try p.clearCofactor().rejectIdentity(); const one = crypto.ecc.Edwards25519.Fe.one; const py = p.y.mul(p.z.invert()); const x = one.add(py).mul(one.sub(py).invert()); // xMont=(1+yEd)/(1-yEd) return Curve25519{ .x = x }; } }