struct Curve25519 [src]
Alias for std.crypto.25519.curve25519.Curve25519
Group operations over Curve25519.
Fields
x: Fe
Members
- basePoint (Constant)
- clampedMul (Function)
- clearCofactor (Function)
- Fe (struct)
- fromBytes (Function)
- fromEdwards25519 (Function)
- mul (Function)
- rejectIdentity (Function)
- rejectNonCanonical (Function)
- scalar (struct)
- toBytes (Function)
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 };
}
}