use core::cmp::Ordering::{self, Equal, Greater};
use core::fmt::{Display, Formatter, LowerHex, UpperHex};
use lazy_static::lazy_static;
use num_bigint_dig as num_bigint;
use thiserror::Error;
use num_bigint::algorithms::jacobi;
use num_bigint::Sign::Plus;
use num_bigint::{BigInt, ModInverse, ParseBigIntError, Sign};
use num_traits::{Num, Signed};
use crate::cipher::stream::Stream;
use crate::encoding::{BinaryMarshaler, BinaryUnmarshaler, Marshaling, MarshallingError};
use crate::group::internal::marshalling;
use crate::group::Scalar;
use crate::util::random::random_int;
use serde::{Deserialize, Serialize};
use crate::group::integer_field::integer::ByteOrder::{BigEndian, LittleEndian};
lazy_static! {
pub static ref ONE: BigInt = BigInt::from(1_i64);
pub static ref TWO: BigInt = BigInt::from(2_i64);
}
const MARSHAL_INT_ID: [u8; 8] = [b'm', b'o', b'd', b'.', b'i', b'n', b't', b' '];
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub enum ByteOrder {
LittleEndian,
BigEndian,
}
impl From<ByteOrder> for bool {
fn from(val: ByteOrder) -> Self {
match val {
LittleEndian => true,
BigEndian => false,
}
}
}
impl From<bool> for ByteOrder {
fn from(b: bool) -> Self {
match b {
true => LittleEndian,
false => BigEndian,
}
}
}
#[derive(Clone, Eq, Debug, Serialize, Deserialize)]
pub struct Int {
pub(crate) v: BigInt,
pub(crate) m: BigInt,
pub bo: ByteOrder,
}
impl Default for Int {
fn default() -> Self {
Int {
bo: LittleEndian,
v: BigInt::from(0),
m: BigInt::from(0),
}
}
}
impl Int {
pub fn init64(mut self, v: i64, m: BigInt) -> Self {
self.m = m.clone();
self.bo = BigEndian;
self.v = BigInt::from(v);
match self.v.sign() {
num_bigint::Sign::Minus => self.v = (self.v % m.clone()) + m.abs(),
_ => self.v %= m,
}
self
}
fn init(mut self, v: BigInt, m: BigInt) -> Self {
self.m = m.clone();
self.bo = BigEndian;
self.v = v % m;
self
}
pub fn little_endian(&self, min: usize, max: usize) -> Result<Vec<u8>, IntError> {
let mut act = self.marshal_size();
let (_, v_bytes) = self.v.to_bytes_be();
let v_size = v_bytes.len();
if v_size < act {
act = v_size;
}
let mut pad = act;
if pad < min {
pad = min
}
if max != 0 && pad > max {
return Err(IntError::NotRepresentable);
}
let buf = vec![0; pad];
let buf2 = &buf[0..act];
Ok(reverse(buf2, &v_bytes))
}
pub fn new_int(v: BigInt, m: BigInt) -> Int {
Int::default().init(v, m)
}
pub fn new_int64(v: i64, m: BigInt) -> Int {
Int::default().init64(v, m)
}
pub fn new_int_bytes(a: &[u8], m: &BigInt, byte_order: ByteOrder) -> Int {
Int::default().init_bytes(a, m, byte_order)
}
pub fn new_int_string(n: String, d: String, base: i32, m: &BigInt) -> Int {
Int::default().init_string(n, d, base, m)
}
pub fn equal(&self, s2: &Self) -> bool {
self.v.cmp(&s2.v) == Equal
}
pub fn cmpr(&self, s2: &Self) -> Ordering {
self.v.cmp(&s2.v)
}
pub fn init_bytes(self, a: &[u8], m: &BigInt, byte_order: ByteOrder) -> Self {
Int {
m: m.clone(),
bo: byte_order,
v: self.v,
}
.set_bytes(a)
}
fn init_string(mut self, n: String, d: String, base: i32, m: &BigInt) -> Int {
self.m = m.clone();
self.bo = BigEndian;
self.set_string(n, d, base)
.expect("init_string: invalid fraction representation")
}
pub fn set_string(mut self, n: String, d: String, base: i32) -> Result<Self, IntError> {
self.v = BigInt::from_str_radix(n.as_str(), base as u32)?;
if !d.is_empty() {
let mut di = Int {
m: self.m.clone(),
..Default::default()
};
di = di.set_string(d, "".to_string(), base)?;
return Ok(self.clone().div(&self, &di));
}
Ok(self)
}
}
impl Display for Int {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
write!(f, "{self:#x}")
}
}
impl PartialEq for Int {
fn eq(&self, other: &Self) -> bool {
self.equal(other)
}
}
impl Ord for Int {
fn cmp(&self, other: &Self) -> Ordering {
self.cmpr(other)
}
}
impl PartialOrd for Int {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmpr(other))
}
}
impl BinaryMarshaler for Int {
fn marshal_binary(&self) -> Result<Vec<u8>, MarshallingError> {
let l = self.marshal_size();
let (_, mut b) = self.v.to_bytes_be();
let offset = l - b.len();
if self.bo == LittleEndian {
return self
.little_endian(l, l)
.map_err(|e| MarshallingError::InvalidInput(e.to_string()));
}
if offset != 0 {
let mut nb = vec![0; l];
nb.splice((offset).., b);
b = nb;
}
Ok(b)
}
}
impl BinaryUnmarshaler for Int {
fn unmarshal_binary(&mut self, data: &[u8]) -> Result<(), MarshallingError> {
let mut buf: Vec<u8> = data.to_vec();
if buf.len() != self.marshal_size() {
return Err(MarshallingError::InvalidInput(
"unmarshal_binary: wrong size buffer".to_owned(),
));
}
if self.bo == LittleEndian {
buf = reverse(&vec![0_u8; buf.len()], &buf.to_vec());
}
self.v = BigInt::from_bytes_be(Plus, buf.as_slice());
if matches!(self.v.cmp(&self.m), Greater | Equal) {
return Err(MarshallingError::InvalidInput(
"unmarshal_binary: value out of range".to_owned(),
));
}
Ok(())
}
}
impl Marshaling for Int {
fn marshal_to(&self, w: &mut impl std::io::Write) -> Result<(), MarshallingError> {
marshalling::scalar_marshal_to(self, w)
}
fn marshal_size(&self) -> usize {
((self.m.bits()) + 7) / 8
}
fn unmarshal_from(&mut self, r: &mut impl std::io::Read) -> Result<(), MarshallingError> {
marshalling::scalar_unmarshal_from(self, r)
}
fn unmarshal_from_random(&mut self, r: &mut (impl std::io::Read + Stream)) {
marshalling::scalar_unmarshal_from_random(self, r);
}
fn marshal_id(&self) -> [u8; 8] {
MARSHAL_INT_ID
}
}
impl LowerHex for Int {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
let prefix = if f.alternate() { "0x" } else { "" };
let encoded = hex::encode(self.v.to_bytes_be().1);
write!(f, "{prefix}{encoded}")
}
}
impl UpperHex for Int {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
let prefix = if f.alternate() { "0X" } else { "" };
let encoded = hex::encode_upper(self.v.to_bytes_be().1);
write!(f, "{prefix}{encoded}")
}
}
use core::ops::{self, Sub};
impl_op_ex!(*|a: &Int, b: &Int| -> Int {
let m = a.m.clone();
let v = (a.v.clone() * b.v.clone()) % m.clone();
let bo = a.bo;
Int { v, m, bo }
});
impl_op_ex!(+|a: &Int, b: &Int| -> Int {
let m = a.m.clone();
let v = (a.v.clone() + b.v.clone()) % m.clone();
let bo = a.bo;
Int{v, m, bo}
});
impl Scalar for Int {
fn set(self, a: &Self) -> Self {
let mut ai = self;
ai.v = a.v.clone();
ai.m = a.m.clone();
ai
}
fn set_int64(self, v: i64) -> Self {
let mut i = self;
i.v = BigInt::from(v);
match i.v.sign() {
num_bigint::Sign::Minus => i.v = (i.v % i.m.clone()) + i.m.abs(),
_ => i.v %= i.m.clone(),
}
i
}
fn zero(self) -> Self {
let mut i = self;
i.v = BigInt::from(0_i64);
i
}
fn sub(mut self, a: &Self, b: &Self) -> Self {
self.m = a.m.clone();
let sub = &a.v - &b.v;
self.v = ((sub % &self.m) + &self.m) % &self.m;
self
}
fn pick(self, rand: &mut impl Stream) -> Self {
let mut s = self.clone();
s.v.clone_from(&random_int(&self.m, rand));
s
}
fn set_bytes(self, a: &[u8]) -> Self {
let mut buff = a.to_vec();
if self.bo == LittleEndian {
buff = reverse(vec![0; buff.len()].as_ref(), a);
}
Int {
m: self.m.clone(),
v: BigInt::from_bytes_be(Plus, buff.as_ref()) % &self.m,
bo: self.bo,
}
}
fn one(self) -> Self {
let mut i = self;
i.v = BigInt::from(1_i64);
i
}
fn div(mut self, a: &Self, b: &Self) -> Self {
let _t = BigInt::default();
self.v = a.v.clone() * b.v.clone();
self.v = self.v.clone() % self.m.clone();
self
}
fn inv(self, a: &Self) -> Self {
let mut i = self;
i.v = a.clone().v.mod_inverse(&a.m.clone()).unwrap();
i.m = a.m.clone();
i
}
fn neg(self, a: &Self) -> Self {
let mut i = self;
i.m = a.m.clone();
i.v = match a.v.sign() {
Plus => a.m.clone().sub(&a.v),
_ => BigInt::from(0_u64),
};
i
}
}
impl Int {
pub fn nonzero(&self) -> bool {
self.v.sign() != Sign::NoSign
}
pub fn int64(&self) -> i64 {
self.uint64() as i64
}
pub fn set_uint64(&self, v: u64) -> Self {
let mut i = self.clone();
i.v = BigInt::from(v) % i.m.clone();
i
}
pub fn uint64(&self) -> u64 {
let mut b = self.v.to_bytes_le().1;
b.resize(8, 0_u8);
let mut a = [0_u8; 8];
for (i, _) in b.iter().enumerate() {
a[i] = b[i];
}
let u = u64::from_le_bytes(a);
match self.v.sign() {
Sign::Minus => core::u64::MAX - u + 1,
_ => u,
}
}
pub fn exp(mut self, a: &Self, e: &BigInt) -> Self {
self.m = a.m.clone();
self.v = self.v.modpow(e, &self.m);
self
}
pub fn jacobi(&self, a_s: &Self) -> Self {
let mut i = self.clone();
i.m = a_s.m.clone();
i.v = BigInt::from(jacobi(&a_s.v, &i.m) as i64);
i
}
pub fn sqrt(&mut self, a_s: &Self) -> Result<(), IntError> {
if a_s.v.sign() == Sign::Minus {
return Err(IntError::ImaginaryRoot);
}
self.v = a_s.v.sqrt() % a_s.m.clone();
self.m = a_s.m.clone();
Ok(())
}
pub fn big_endian(&self, min: usize, max: usize) -> Result<Vec<u8>, IntError> {
let act = self.marshal_size();
let (mut pad, mut ofs) = (act, 0);
if pad < min {
(pad, ofs) = (min, min - act)
}
if max != 0 && pad > max {
return Err(IntError::NotRepresentable);
}
let mut buf = vec![0_u8; pad];
let b = self.v.to_bytes_be().1;
buf[ofs..].copy_from_slice(&b);
Ok(buf)
}
}
fn reverse(dst: &[u8], src: &[u8]) -> Vec<u8> {
let mut dst = dst.to_vec();
let l = dst.len();
for i in 0..(l + 1) / 2 {
let j = l - 1 - i;
(dst[i], dst[j]) = (src[j], src[i]);
}
dst.to_vec()
}
#[derive(Debug, Error)]
pub enum IntError {
#[error("marshalling error")]
MarshallingError(#[from] MarshallingError),
#[error("parse big int error")]
ParseBigIntError(#[from] ParseBigIntError),
#[error("Int not representable in max bytes")]
NotRepresentable,
#[error("input is a negative number, square root is imaginary")]
ImaginaryRoot,
}