《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》