diff --git a/src/lib.rs b/src/lib.rs index 21f0b14..6ef5ccd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -206,31 +206,75 @@ impl Point { false } - // // Use a variation of the Koblitz method - // pub fn from_msg_vartime(msg: &[u8; 28]) -> Point { - // } - - pub fn from_msg(msg: &[u8; 28]) -> Point { + // Use a variation of the Koblitz method + pub fn from_msg_vartime(msg: BigInt/*msg: &[u8; 28]*/) -> Point { // This is the largest point that can fit BabyJubJub curve while still allowing 8 extra bytes, as long as those bytes are less than f0000001 // Babyjubjub r parameter is 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 - assert!( - BigInt::from_bytes_be(Sign::Plus, msg) - < - BigInt::parse_bytes(b"30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001",16).unwrap() - ); - let mut acc: u32 = 0; - let mut pt: Point; - let mut is_residue: bool = false; + // assert!( + // BigInt::from_bytes_be(Sign::Plus, msg) + // < + // BigInt::parse_bytes(b"30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000",16).unwrap() + // ); + // let mut acc: u32 = 0; + // let mut pt: Point; + // let mut is_residue: bool = false; + // let mut on_curve: bool = false; + // while (acc <= 0xf0000001) && !on_curve { + // let acc_bytes: [u8; 4] = acc.to_be_bytes(); + // // let mut buff: ArrayVec::<[u8; 32]> = concat_bytes!()[msg, acc_bytes]); + // let mut buf = BytesMut::with_capacity(32); + // buf.put_slice(msg); + // buf.put_u32(acc); + // Fr::from_str("123").unwrap().legendre() + // println!("bytes {:?}", buf); + // } + + // Koblitz decoding method, adapted for this curve: + // message m must be < r/10000 + // Try finding a point with y value m*10000+0, m*10000+1, .... m*10000+5617 (5617 are last four digits of prime r) + // There is an approximately 1/(2^1000) chance no point will be encodable, + // since each y value has probability of about 1/2 of being on the curve + let MAX_MSG: BigInt = BigInt::parse_bytes( + b"2188824287183927522224640574525727508854836440041603434369820418657580849",10 // Prime r but missing last 4 digits + ).unwrap(); + let ACC_UNDER = 5617; // Last four digits of prime r. MAX_MSG * 10000 + ACC_UNDER = r + assert!(msg <= MAX_MSG); + let mut acc: u16 = 0; let mut on_curve: bool = false; - while (acc <= 0xf0000001) && !on_curve { - let acc_bytes: [u8; 4] = acc.to_be_bytes(); - // let mut buff: ArrayVec::<[u8; 32]> = concat_bytes!()[msg, acc_bytes]); - let mut buf = BytesMut::with_capacity(32); - buf.put_slice(msg); - buf.put_u32(acc); - println!("bytes {:?}", buf); + // Start with message * 10000 as x coordinate + let mut x: Fr = Fr::from_str(&msg.to_str_radix(10)).unwrap(); + let mut y: Option = None; + x.mul_assign(&Fr::from_str("10000").unwrap()); + + let one = Fr::one(); + // let m10000 = 1000.to_bigint().unwrap() * msg; + while (acc < ACC_UNDER) && !on_curve { + // If x is on curve, calculate what y^2 should be, by (ax^2 - 1) / (dx^2 - 1) + let mut x2 = x.clone(); + x2.mul_assign(&x); + + // Numerator will be (ax^2 - 1) and denominator will be (dx^2 - 1) + let mut numerator = x2; + let mut denominator = x2.clone(); + + numerator.mul_assign(&A); + denominator.mul_assign(&D); + + numerator.sub_assign(&one); + denominator.sub_assign(&one); + + // If the point is on the curve, numerator/denominator will be y^2. Check whether numerator/denominator is a quadratic residue: + numerator.mul_assign(&denominator.inverse().unwrap()); // Note: this is no longer a numerator since it was divided in this step + if let LegendreSymbol::QuadraticResidue = numerator.legendre() { + on_curve=true; + y = numerator.sqrt(); + } else { + acc += 1; + } } - Point {x:Fr::zero(), y:Fr::zero()} + // Unwrap y since we can't be 100% sure at compile-time it will have been found; it may still be a None value! + Point {x:x, y:y.unwrap()} + } pub fn on_curve(&self) -> bool {