aurora_engine_modexp/
lib.rs
1#![cfg_attr(not(feature = "std"), no_std)]
2#![allow(
5 clippy::as_conversions,
6 clippy::cast_possible_wrap,
7 clippy::cast_possible_truncation,
8 clippy::cast_lossless,
9 clippy::many_single_char_names
10)]
11
12mod arith;
13mod maybe_std;
14mod mpnat;
15
16use maybe_std::Vec;
17
18pub trait ModExpAlgorithm: 'static {
22 fn modexp(base: &[u8], exp: &[u8], modulus: &[u8]) -> Vec<u8>;
24}
25
26pub struct AuroraModExp;
27
28impl ModExpAlgorithm for AuroraModExp {
29 fn modexp(base: &[u8], exp: &[u8], modulus: &[u8]) -> Vec<u8> {
30 modexp(base, exp, modulus)
31 }
32}
33
34#[must_use]
37pub fn modexp(base: &[u8], exp: &[u8], modulus: &[u8]) -> Vec<u8> {
38 let mut x = mpnat::MPNat::from_big_endian(base);
39 let m = mpnat::MPNat::from_big_endian(modulus);
40 if m.digits.len() == 1 && m.digits[0] == 0 {
41 return Vec::new();
42 }
43 let result = x.modpow(exp, &m);
44 result.to_big_endian()
45}
46
47#[cfg(feature = "bench")]
48pub fn modexp_ibig(base: &[u8], exp: &[u8], modulus: &[u8]) -> Vec<u8> {
49 use num::Zero;
50
51 let base = ibig::UBig::from_be_bytes(base);
52 let modulus = ibig::UBig::from_be_bytes(modulus);
53 if modulus.is_zero() {
54 return Vec::new();
55 }
56 let exponent = ibig::UBig::from_be_bytes(exp);
57 let ring = ibig::modular::ModuloRing::new(&modulus);
58 let result = ring.from(base).pow(&exponent);
59 result.residue().to_be_bytes()
60}
61
62#[cfg(feature = "bench")]
63pub fn modexp_num(base: &[u8], exp: &[u8], modulus: &[u8]) -> Vec<u8> {
64 use num::Zero;
65
66 let base = num::BigUint::from_bytes_be(base);
67 let modulus = num::BigUint::from_bytes_be(modulus);
68 if modulus.is_zero() {
69 return Vec::new();
70 }
71 let exponent = num::BigUint::from_bytes_be(exp);
72 base.modpow(&exponent, &modulus).to_bytes_be()
73}