大(负)数的模乘反函数
Modular multiplicative inverse function for big (negative) numbers
模乘逆在密码学中被广泛使用。我有 following program in rust 用于使用扩展欧几里得算法计算模乘逆:
extern crate num;
use num::bigint::BigInt;
use num::Integer;
use num::One;
use num::Zero;
fn modinv(n: &BigInt, p: &BigInt) -> BigInt {
if p.is_one() { return BigInt::one() }
let (mut a, mut m, mut x, mut inv) = (n.clone(), p.clone(), BigInt::zero(), BigInt::one());
while a > BigInt::one() {
let (div, rem) = a.div_rem(&m);
inv -= div * &x;
a = rem;
std::mem::swap(&mut a, &mut m);
std::mem::swap(&mut x, &mut inv);
}
if inv < BigInt::zero() { inv += p }
inv
}
fn main() {
let n = BigInt::parse_bytes(b"-243772585612020160733370897338805215918303827399330592839196552441720391139", 10).unwrap();
let p = BigInt::parse_bytes(b"115792089237316195423570985008687907853269984665640564039457584007908834671663", 10).unwrap();
println!("modinv({0}, {1}) = {2}", n, p, modinv(&n, &p));
}
这对正数 n
和 p
很好用,但是当 n
像上面的情况一样是负数时,我得到以下输出:
modinv(-243772585612020160733370897338805215918303827399330592839196552441720391139, 115792089237316195423570985008687907853269984665640564039457584007908834671663) = 1
输出 1
不正确,我想要以下输出(使用 python shell):
In [1]: n = -243772585612020160733370897338805215918303827399330592839196552441720391139
In [2]: p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
In [3]: pow(n, -1, p)
Out[3]: 78090076461723887468177075808811701300309702327169440891599636163808855875538
有没有办法改变上面的 modinv
函数,使其也像 python 一样处理负数?
在 a
、m
、x
和 inv
的定义正下方添加行 while a < BigInt::zero() { a += p }
应该可以解决问题,使用事实a % m == a + m % m
.
模乘逆在密码学中被广泛使用。我有 following program in rust 用于使用扩展欧几里得算法计算模乘逆:
extern crate num;
use num::bigint::BigInt;
use num::Integer;
use num::One;
use num::Zero;
fn modinv(n: &BigInt, p: &BigInt) -> BigInt {
if p.is_one() { return BigInt::one() }
let (mut a, mut m, mut x, mut inv) = (n.clone(), p.clone(), BigInt::zero(), BigInt::one());
while a > BigInt::one() {
let (div, rem) = a.div_rem(&m);
inv -= div * &x;
a = rem;
std::mem::swap(&mut a, &mut m);
std::mem::swap(&mut x, &mut inv);
}
if inv < BigInt::zero() { inv += p }
inv
}
fn main() {
let n = BigInt::parse_bytes(b"-243772585612020160733370897338805215918303827399330592839196552441720391139", 10).unwrap();
let p = BigInt::parse_bytes(b"115792089237316195423570985008687907853269984665640564039457584007908834671663", 10).unwrap();
println!("modinv({0}, {1}) = {2}", n, p, modinv(&n, &p));
}
这对正数 n
和 p
很好用,但是当 n
像上面的情况一样是负数时,我得到以下输出:
modinv(-243772585612020160733370897338805215918303827399330592839196552441720391139, 115792089237316195423570985008687907853269984665640564039457584007908834671663) = 1
输出 1
不正确,我想要以下输出(使用 python shell):
In [1]: n = -243772585612020160733370897338805215918303827399330592839196552441720391139
In [2]: p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
In [3]: pow(n, -1, p)
Out[3]: 78090076461723887468177075808811701300309702327169440891599636163808855875538
有没有办法改变上面的 modinv
函数,使其也像 python 一样处理负数?
在 a
、m
、x
和 inv
的定义正下方添加行 while a < BigInt::zero() { a += p }
应该可以解决问题,使用事实a % m == a + m % m
.