1. curve25519以montgomery表示下的basepoint
《Elliptic Curves for Security rfc7748》中说明,curve25519对应montgomery形式和basepoint如下:
因此对应的代码有:
/// The X25519 basepoint, in `MontgomeryPoint` format.
pub const X25519_BASEPOINT: MontgomeryPoint =
MontgomeryPoint([0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
2. curve25519以edwards25519表示下的basepoint
《Elliptic Curves for Security rfc7748》中说明,curve25519对应edwards形式和basepoint如下:
由affine坐标系转换为extended坐标系的映射方法为:
(
x
,
y
)
↦
(
X
:
Y
:
Z
:
T
)
:
Z
=
1
,
T
=
X
Y
,
X
=
x
/
Z
,
Y
=
y
/
Z
(x,y)\mapsto (X:Y:Z:T):\ Z=1,T=XY,X=x/Z,Y=y/Z
(x,y)↦(X:Y:Z:T): Z=1,T=XY,X=x/Z,Y=y/Z
/// The Ed25519 basepoint, as an `EdwardsPoint`.
///
/// This is called `_POINT` to distinguish it from
/// `ED25519_BASEPOINT_TABLE`, which should be used for scalar
/// multiplication (it's much faster).
pub const ED25519_BASEPOINT_POINT: EdwardsPoint = EdwardsPoint{
X: FieldElement51([1738742601995546, 1146398526822698, 2070867633025821, 562264141797630, 587772402128613]),
Y: FieldElement51([1801439850948184, 1351079888211148, 450359962737049, 900719925474099, 1801439850948198]),
Z: FieldElement51([1, 0, 0, 0, 0]),
T: FieldElement51([1841354044333475, 16398895984059, 755974180946558, 900171276175154, 1821297809914039]),
};
对应的 sage脚本为:
sage: p=2^255-19
sage: x=151122213495354007725011514095885315114540126930418572060461132839498477
....: 62202
sage: y=463168356949264781694283940034751631413079938662562256157830336031652518
....: 55960
sage: t=mod(x*y,p)
sage: t
46827403850823179245072216630277197565144205554125654976674165829533817101731
sage: 1841354044333475+16398895984059*2^51+755974180946558*2^102+900171276175154
....: *2^153+1821297809914039*2^204
46827403850823179245072216630277197565144205554125654976674165829533817101731
sage: 1738742601995546+1146398526822698*2^51+2070867633025821*2^102+562264141797
....: 630*2^153+587772402128613*2^204
15112221349535400772501151409588531511454012693041857206046113283949847762202
sage: 1801439850948184+1351079888211148*2^51+450359962737049*2^102+9007199254740
....: 99*2^153+1801439850948198*2^204
46316835694926478169428394003475163141307993866256225615783033603165251855960
根据博客edwards25519 point压缩及解压缩算法中说明,basepoint的压缩表示为:
pub const ED25519_BASEPOINT_COMPRESSED: CompressedEdwardsY =
CompressedEdwardsY([0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66]);
对应的sage证明为:
sage: x=151122213495354007725011514095885315114540126930418572060461132839498477
....: 62202
sage: y=463168356949264781694283940034751631413079938662562256157830336031652518
....: 55960
sage: hex(x&1)
'0'
sage: ((x&1)<<255)|y
46316835694926478169428394003475163141307993866256225615783033603165251855960
sage: hex( ((x&1)<<255)|y)
'6666666666666666666666666666666666666666666666666666666666666658'
sage:
3. curve25519以RISTRETTO表示下的basepoint
ristretto255中使用的时prime order group,其中的point以extended坐标系 ( X : Y : Z : T ) (X:Y:Z:T) (X:Y:Z:T)表示,对应的basepoint表示为:
// ------------------------------------------------------------------------
// Internal point representations
// ------------------------------------------------------------------------
/// A `RistrettoPoint` represents a point in the Ristretto group for
/// Curve25519. Ristretto, a variant of Decaf, constructs a
/// prime-order group as a quotient group of a subgroup of (the
/// Edwards form of) Curve25519.
///
/// Internally, a `RistrettoPoint` is implemented as a wrapper type
/// around `EdwardsPoint`, with custom equality, compression, and
/// decompression routines to account for the quotient. This means that
/// operations on `RistrettoPoint`s are exactly as fast as operations on
/// `EdwardsPoint`s.
///
#[derive(Copy, Clone)]
pub struct RistrettoPoint(pub(crate) EdwardsPoint);
/// The Ristretto basepoint, as a `RistrettoPoint`.
///
/// This is called `_POINT` to distinguish it from `_TABLE`, which
/// provides fast scalar multiplication.
pub const RISTRETTO_BASEPOINT_POINT: RistrettoPoint = RistrettoPoint(ED25519_BASEPOINT_POINT);
/// The Ed25519 basepoint, as an `EdwardsPoint`.
///
/// This is called `_POINT` to distinguish it from
/// `ED25519_BASEPOINT_TABLE`, which should be used for scalar
/// multiplication (it's much faster).
pub const ED25519_BASEPOINT_POINT: EdwardsPoint = EdwardsPoint{
X: FieldElement51([1738742601995546, 1146398526822698, 2070867633025821, 562264141797630, 587772402128613]),
Y: FieldElement51([1801439850948184, 1351079888211148, 450359962737049, 900719925474099, 1801439850948198]),
Z: FieldElement51([1, 0, 0, 0, 0]),
T: FieldElement51([1841354044333475, 16398895984059, 755974180946558, 900171276175154, 1821297809914039]),
};
可对RistrettoPoint进行压缩,压缩算法见博客ristretto255 point压缩和解压缩算法(2)——extended坐标系下。
basepoint压缩后表示为:【注意,采用的是little-endian展示的】
压缩方式为:
let B = &constants::RISTRETTO_BASEPOINT_POINT;
hex::encode(B.compress().as_bytes());//"e2f2ae0a6abc4e71a884a961c500515f58e30b6aa582dd8db6a65945e08d2d76"
/// Compress this point using the Ristretto encoding.
pub fn compress(&self) -> CompressedRistretto {
let mut X = self.0.X;
let mut Y = self.0.Y;
let Z = &self.0.Z;
let T = &self.0.T;
let u1 = &(Z + &Y) * &(Z - &Y);
let u2 = &X * &Y;
// Ignore return value since this is always square
let (_, invsqrt) = (&u1 * &u2.square()).invsqrt();
let i1 = &invsqrt * &u1;
let i2 = &invsqrt * &u2;
let z_inv = &i1 * &(&i2 * T);
let mut den_inv = i2;
let iX = &X * &constants::SQRT_M1;
let iY = &Y * &constants::SQRT_M1;
let ristretto_magic = &constants::INVSQRT_A_MINUS_D;
let enchanted_denominator = &i1 * ristretto_magic;
let rotate = (T * &z_inv).is_negative();
X.conditional_assign(&iY, rotate);
Y.conditional_assign(&iX, rotate);
den_inv.conditional_assign(&enchanted_denominator, rotate);
Y.conditional_negate((&X * &z_inv).is_negative());
let mut s = &den_inv * &(Z - &Y);
let s_is_negative = s.is_negative();
s.conditional_negate(s_is_negative);
CompressedRistretto(s.to_bytes())
}
/// Determine if this `FieldElement` is negative, in the sense
/// used in the ed25519 paper: `x` is negative if the low bit is
/// set.
///
/// # Return
///
/// If negative, return `Choice(1)`. Otherwise, return `Choice(0)`.
pub fn is_negative(&self) -> Choice {
let bytes = self.to_bytes();
(bytes[0] & 1).into()
}
/// A Ristretto point, in compressed wire format.
///
/// The Ristretto encoding is canonical, so two points are equal if and
/// only if their encodings are equal.
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct CompressedRistretto(pub [u8; 32]);
/// The Ristretto basepoint, in `CompressedRistretto` format.
pub const RISTRETTO_BASEPOINT_COMPRESSED: CompressedRistretto =
CompressedRistretto([0xe2, 0xf2, 0xae, 0x0a, 0x6a, 0xbc, 0x4e, 0x71,
0xa8, 0x84, 0xa9, 0x61, 0xc5, 0x00, 0x51, 0x5f,
0x58, 0xe3, 0x0b, 0x6a, 0xa5, 0x82, 0xdd, 0x8d,
0xb6, 0xa6, 0x59, 0x45, 0xe0, 0x8d, 0x2d, 0x76]);
参考资料:
[1] 《Elliptic Curves for Security rfc7748》
[2] 《The ristretto255 Group draft-hdevalence-cfrg-ristretto-01》