g1 from compressed api

This commit is contained in:
NikVolf
2019-04-16 16:51:52 +03:00
parent 78fddbb743
commit 309ab3c579
4 changed files with 98 additions and 0 deletions
+1
View File
@@ -1,2 +1,3 @@
target
Cargo.lock
.idea
+2
View File
@@ -20,6 +20,8 @@ rand = { version = "0.5", features = ["i128_support"] }
rustc-serialize = { version = "0.3", optional = true }
byteorder = { version = "1.0", features = ["i128"] }
crunchy = "0.2.1"
lazy_static = "*"
rustc-hex = "2"
[dev-dependencies.bincode]
version = "0.6"
+38
View File
@@ -240,6 +240,44 @@ field_impl!(
0x9ede7d651eca6ac987d20782e4866389
);
lazy_static! {
static ref FQ: U256 = U256::from([
0x3c208c16d87cfd47,
0x97816a916871ca8d,
0xb85045b68181585d,
0x30644e72e131a029
]);
static ref FQ_MINUS3_DIV4: Fq =
Fq::new(3.into()).expect("3 is a valid field element and static; qed").neg() *
Fq::new(4.into()).expect("4 is a valid field element and static; qed").inverse()
.expect("4 has inverse in Fq and is static; qed");
static ref FQ_MINUS1_DIV2: Fq =
Fq::new(1.into()).expect("1 is a valid field element and static; qed").neg() *
Fq::new(2.into()).expect("2 is a valid field element and static; qed").inverse()
.expect("2 has inverse in Fq and is static; qed");
}
impl Fq {
pub fn sqrt(&self) -> Option<Self> {
let a1 = self.pow(*FQ_MINUS3_DIV4);
let a1a = a1 * *self;
let a0 = a1 * (a1a);
let mut am1 = *FQ;
am1.sub(&1.into(), &*FQ);
if a0 == Fq::new(am1).unwrap() {
None
} else {
Some(a1a)
}
}
}
#[inline]
pub fn const_fq(i: [u64; 4]) -> Fq {
Fq(U256::from(i))
+57
View File
@@ -4,6 +4,7 @@ extern crate crunchy;
extern crate rand;
#[cfg(feature = "rustc-serialize")]
extern crate rustc_serialize;
#[macro_use] extern crate lazy_static;
pub mod arith;
mod fields;
@@ -108,6 +109,19 @@ pub enum FieldError {
NotMember,
}
#[derive(Debug)]
pub enum CurveError {
InvalidEncoding,
NotMember,
Field(FieldError),
}
impl From<FieldError> for CurveError {
fn from(fe: FieldError) -> Self {
CurveError::Field(fe)
}
}
pub use groups::Error as GroupError;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -166,6 +180,10 @@ impl Fq {
pub fn modulus() -> arith::U256 {
fields::Fq::modulus()
}
pub fn sqrt(&self) -> Option<Self> {
self.0.sqrt().map(Fq)
}
}
impl Add<Fq> for Fq {
@@ -328,6 +346,24 @@ impl G1 {
pub fn b() -> Fq {
Fq(G1Params::coeff_b())
}
pub fn from_compressed(bytes: &[u8]) -> Result<Self, CurveError> {
if bytes.len() != 33 { return Err(CurveError::InvalidEncoding); }
let sign = bytes[0];
let fq = Fq::from_slice(&bytes[1..])?;
let x = fq;
let y_squared = (fq * fq * fq) + Self::b();
let mut y = y_squared.sqrt().ok_or(CurveError::NotMember)?;
if sign == 2 && y.into_u256().get_bit(0).expect("bit 0 always exist; qed") { y = y.neg(); }
else if sign == 3 && !y.into_u256().get_bit(0).expect("bit 0 always exist; qed") { y = y.neg(); }
else if sign != 3 && sign != 2 {
return Err(CurveError::InvalidEncoding);
}
AffineG1::new(x, y).map_err(|_| CurveError::NotMember).map(Into::into)
}
}
impl Group for G1 {
@@ -580,3 +616,24 @@ impl From<AffineG2> for G2 {
G2(affine.0.to_jacobian())
}
}
#[cfg(test)]
mod tests {
extern crate rustc_hex as hex;
use super::{G1, Fq};
fn hex(s: &'static str) -> Vec<u8> {
use self::hex::FromHex;
s.from_hex().unwrap()
}
#[test]
fn g1_from_compressed() {
let g1 = G1::from_compressed(&hex("0230644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"))
.expect("Invalid g1 decompress result");
assert_eq!(g1.x(), Fq::from_str("21888242871839275222246405745257275088696311157297823662689037894645226208582").unwrap());
assert_eq!(g1.y(), Fq::from_str("3969792565221544645472939191694882283483352126195956956354061729942568608776").unwrap());
assert_eq!(g1.z(), Fq::one());
}
}