加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
bignum.c 10.36 KB
一键复制 编辑 原始数据 按行查看 历史
Chuck 提交于 2018-01-19 23:44 . Initial commit
/*****************************************************************************
Filename: bignum.c
Author : Chuck Li (lch0821@foxmail.com)
Date : 2018-01-19 12:38:46
Description:
*****************************************************************************/
#include <string.h>
#include "bignum.h"
extern void print_bn(char *TAG, bn_t *bn, uint32_t bn_size);
static bn_t bn_sub_digit_mul(bn_t *a, bn_t *b, bn_t c, bn_t *d, uint32_t digits);
static bn_t bn_add_digit_mul(bn_t *a, bn_t *b, bn_t c, bn_t *d, uint32_t digits);
static uint32_t bn_digit_bits(bn_t a);
void bn_decode(bn_t *bn, uint32_t digits, uint8_t *hexarr, uint32_t size)
{
bn_t t;
int j;
uint32_t i, u;
for(i=0,j=size-1; i<digits && j>=0; i++) {
t = 0;
for(u=0; j>=0 && u<BN_DIGIT_BITS; j--, u+=8) {
t |= ((bn_t)hexarr[j]) << u;
}
bn[i] = t;
}
for(; i<digits; i++) {
bn[i] = 0;
}
}
void bn_encode(uint8_t *hexarr, uint32_t size, bn_t *bn, uint32_t digits)
{
bn_t t;
int j;
uint32_t i, u;
for(i=0,j=size-1; i<digits && j>=0; i++) {
t = bn[i];
for(u=0; j>=0 && u<BN_DIGIT_BITS; j--, u+=8) {
hexarr[j] = (uint8_t)(t >> u);
}
}
for(; j>=0; j--) {
hexarr[j] = 0;
}
}
void bn_assign(bn_t *a, bn_t *b, uint32_t digits)
{
uint32_t i;
for(i=0; i<digits; i++) {
a[i] = b[i];
}
}
void bn_assign_zero(bn_t *a, uint32_t digits)
{
uint32_t i;
for(i=0; i<digits; i++) {
a[i] = 0;
}
}
void bn_assign_2exp(bn_t *a, uint32_t b, uint32_t digits)
{
bn_assign_zero(a, digits);
if(b >= (digits * BN_DIGIT_BITS)) {
return; // Out of range
}
a[b/BN_DIGIT_BITS] = (bn_t)1 << (b % BN_DIGIT_BITS);
}
bn_t bn_add(bn_t *a, bn_t *b, bn_t *c, uint32_t digits)
{
bn_t ai, carry;
uint32_t i;
carry = 0;
for(i=0; i<digits; i++) {
if((ai = b[i] + carry) < carry) {
ai = c[i];
} else if((ai += c[i]) < c[i]) {
carry = 1;
} else {
carry = 0;
}
a[i] = ai;
}
return carry;
}
bn_t bn_sub(bn_t *a, bn_t *b, bn_t *c, uint32_t digits)
{
bn_t ai, borrow;
uint32_t i;
borrow = 0;
for(i=0; i<digits; i++) {
if((ai = b[i] - borrow) > (BN_MAX_DIGIT - borrow)) {
ai = BN_MAX_DIGIT - c[i];
} else if((ai -= c[i]) > (BN_MAX_DIGIT - c[i])) {
borrow = 1;
} else {
borrow = 0;
}
a[i] = ai;
}
return borrow;
}
void bn_mul(bn_t *a, bn_t *b, bn_t *c, uint32_t digits)
{
bn_t t[2*BN_MAX_DIGITS];
uint32_t bdigits, cdigits, i;
bn_assign_zero(t, 2*digits);
bdigits = bn_digits(b, digits);
cdigits = bn_digits(c, digits);
for(i=0; i<bdigits; i++) {
t[i+cdigits] += bn_add_digit_mul(&t[i], &t[i], b[i], c, cdigits);
}
bn_assign(a, t, 2*digits);
// Clear potentially sensitive information
memset((uint8_t *)t, 0, sizeof(t));
}
void bn_div(bn_t *a, bn_t *b, bn_t *c, uint32_t cdigits, bn_t *d, uint32_t ddigits)
{
dbn_t tmp;
bn_t ai, t, cc[2*BN_MAX_DIGITS+1], dd[BN_MAX_DIGITS];
int i;
uint32_t dddigits, shift;
dddigits = bn_digits(d, ddigits);
if(dddigits == 0)
return;
shift = BN_DIGIT_BITS - bn_digit_bits(d[dddigits-1]);
bn_assign_zero(cc, dddigits);
cc[cdigits] = bn_shift_l(cc, c, shift, cdigits);
bn_shift_l(dd, d, shift, dddigits);
t = dd[dddigits-1];
bn_assign_zero(a, cdigits);
i = cdigits - dddigits;
for(; i>=0; i--) {
if(t == BN_MAX_DIGIT) {
ai = cc[i+dddigits];
} else {
tmp = cc[i+dddigits-1];
tmp += (dbn_t)cc[i+dddigits] << BN_DIGIT_BITS;
ai = tmp / (t + 1);
}
cc[i+dddigits] -= bn_sub_digit_mul(&cc[i], &cc[i], ai, dd, dddigits);
// printf("cc[%d]: %08X\n", i, cc[i+dddigits]);
while(cc[i+dddigits] || (bn_cmp(&cc[i], dd, dddigits) >= 0)) {
ai++;
cc[i+dddigits] -= bn_sub(&cc[i], &cc[i], dd, dddigits);
}
a[i] = ai;
// printf("ai[%d]: %08X\n", i, ai);
}
bn_assign_zero(b, ddigits);
bn_shift_r(b, cc, shift, dddigits);
// Clear potentially sensitive information
memset((uint8_t *)cc, 0, sizeof(cc));
memset((uint8_t *)dd, 0, sizeof(dd));
}
bn_t bn_shift_l(bn_t *a, bn_t *b, uint32_t c, uint32_t digits)
{
bn_t bi, carry;
uint32_t i, t;
if(c >= BN_DIGIT_BITS)
return 0;
t = BN_DIGIT_BITS - c;
carry = 0;
for(i=0; i<digits; i++) {
bi = b[i];
a[i] = (bi << c) | carry;
carry = c ? (bi >> t) : 0;
}
return carry;
}
bn_t bn_shift_r(bn_t *a, bn_t *b, uint32_t c, uint32_t digits)
{
bn_t bi, carry;
int i;
uint32_t t;
if(c >= BN_DIGIT_BITS)
return 0;
t = BN_DIGIT_BITS - c;
carry = 0;
i = digits - 1;
for(; i>=0; i--) {
bi = b[i];
a[i] = (bi >> c) | carry;
carry = c ? (bi << t) : 0;
}
return carry;
}
void bn_mod(bn_t *a, bn_t *b, uint32_t bdigits, bn_t *c, uint32_t cdigits)
{
bn_t t[2*BN_MAX_DIGITS] = {0};
// print_bn("b", b, bdigits);
// print_bn("c", c, cdigits);
bn_div(t, a, b, bdigits, c, cdigits);
// print_bn("t", t, 2*BN_MAX_DIGITS);
// Clear potentially sensitive information
memset((uint8_t *)t, 0, sizeof(t));
}
void bn_mod_mul(bn_t *a, bn_t *b, bn_t *c, bn_t *d, uint32_t digits)
{
bn_t t[2*BN_MAX_DIGITS];
bn_mul(t, b, c, digits);
bn_mod(a, t, 2*digits, d, digits);
// Clear potentially sensitive information
memset((uint8_t *)t, 0, sizeof(t));
}
void bn_mod_exp(bn_t *a, bn_t *b, bn_t *c, uint32_t cdigits, bn_t *d, uint32_t ddigits)
{
bn_t bpower[3][BN_MAX_DIGITS], ci, t[BN_MAX_DIGITS];
int i;
uint32_t ci_bits, j, s;
bn_assign(bpower[0], b, ddigits);
bn_mod_mul(bpower[1], bpower[0], b, d, ddigits);
bn_mod_mul(bpower[2], bpower[1], b, d, ddigits);
BN_ASSIGN_DIGIT(t, 1, ddigits);
cdigits = bn_digits(c, cdigits);
i = cdigits - 1;
for(; i>=0; i--) {
ci = c[i];
ci_bits = BN_DIGIT_BITS;
if(i == (int)(cdigits - 1)) {
while(!DIGIT_2MSB(ci)) {
ci <<= 2;
ci_bits -= 2;
}
}
for(j=0; j<ci_bits; j+=2) {
bn_mod_mul(t, t, t, d, ddigits);
bn_mod_mul(t, t, t, d, ddigits);
if((s = DIGIT_2MSB(ci)) != 0) {
bn_mod_mul(t, t, bpower[s-1], d, ddigits);
}
ci <<= 2;
}
}
bn_assign(a, t, ddigits);
// Clear potentially sensitive information
memset((uint8_t *)bpower, 0, sizeof(bpower));
memset((uint8_t *)t, 0, sizeof(t));
}
void bn_mod_inv(bn_t *a, bn_t *b, bn_t *c, uint32_t digits)
{
bn_t q[BN_MAX_DIGITS], t1[BN_MAX_DIGITS], t3[BN_MAX_DIGITS], w[2*BN_MAX_DIGITS];
bn_t u1[BN_MAX_DIGITS], u3[BN_MAX_DIGITS], v1[BN_MAX_DIGITS], v3[BN_MAX_DIGITS];
int u1_sign;
BN_ASSIGN_DIGIT(u1, 1, digits);
bn_assign_zero(v1, digits);
bn_assign(u3, b, digits);
bn_assign(v3, c, digits);
u1_sign = 1;
while(!bn_is_zero(v3, digits)) {
bn_div(q, t3, u3, digits, v3, digits);
bn_mul(w, q, v1, digits);
bn_add(t1, u1, w, digits);
bn_assign(u1, v1, digits);
bn_assign(v1, t1, digits);
bn_assign(u3, v3, digits);
bn_assign(v3, t3, digits);
u1_sign = -u1_sign;
}
if(u1_sign < 0) {
bn_sub(a, c, u1, digits);
} else {
bn_assign(a, u1, digits);
}
// Clear potentially sensitive information
memset((uint8_t *)q, 0, sizeof(q));
memset((uint8_t *)t1, 0, sizeof(t1));
memset((uint8_t *)t3, 0, sizeof(t3));
memset((uint8_t *)u1, 0, sizeof(u1));
memset((uint8_t *)u3, 0, sizeof(u3));
memset((uint8_t *)v1, 0, sizeof(v1));
memset((uint8_t *)v3, 0, sizeof(v3));
memset((uint8_t *)w, 0, sizeof(w));
}
void bn_gcd(bn_t *a, bn_t *b, bn_t *c, uint32_t digits)
{
bn_t t[BN_MAX_DIGITS], u[BN_MAX_DIGITS], v[BN_MAX_DIGITS];
bn_assign(u, b, digits);
bn_assign(v, c, digits);
while(!bn_is_zero(v, digits)) {
bn_mod(t, u, digits, v, digits);
bn_assign(u, v, digits);
bn_assign(v, t, digits);
}
bn_assign(a, u, digits);
// Clear potentially sensitive information
memset((uint8_t *)t, 0, sizeof(t));
memset((uint8_t *)u, 0, sizeof(u));
memset((uint8_t *)v, 0, sizeof(v));
}
int bn_cmp(bn_t *a, bn_t *b, uint32_t digits)
{
int i;
for(i=digits-1; i>=0; i--) {
if(a[i] > b[i]) return 1;
if(a[i] < b[i]) return -1;
}
return 0;
}
int bn_is_zero(bn_t *a, uint32_t digits)
{
uint32_t i;
for(i=0; i<digits; i++) {
if(a[i]) {
return 0;
}
}
return 1;
}
uint32_t bn_bits(bn_t *a, uint32_t digits)
{
if((digits = bn_digits(a, digits)) == 0) {
return 0;
}
return ((digits - 1) * BN_DIGIT_BITS + bn_digit_bits(a[digits-1]));
}
uint32_t bn_digits(bn_t *a, uint32_t digits)
{
int i;
for(i=digits-1; i>=0; i--) {
if(a[i]) break;
}
return (i + 1);
}
static bn_t bn_add_digit_mul(bn_t *a, bn_t *b, bn_t c, bn_t *d, uint32_t digits)
{
dbn_t result;
bn_t carry, rh, rl;
uint32_t i;
if(c == 0)
return 0;
carry = 0;
for(i=0; i<digits; i++) {
result = (dbn_t)c * d[i];
rl = result & BN_MAX_DIGIT;
rh = (result >> BN_DIGIT_BITS) & BN_MAX_DIGIT;
if((a[i] = b[i] + carry) < carry) {
carry = 1;
} else {
carry = 0;
}
if((a[i] += rl) < rl) {
carry++;
}
carry += rh;
}
return carry;
}
static bn_t bn_sub_digit_mul(bn_t *a, bn_t *b, bn_t c, bn_t *d, uint32_t digits)
{
dbn_t result;
bn_t borrow, rh, rl;
uint32_t i;
if(c == 0)
return 0;
borrow = 0;
for(i=0; i<digits; i++) {
result = (dbn_t)c * d[i];
rl = result & BN_MAX_DIGIT;
rh = (result >> BN_DIGIT_BITS) & BN_MAX_DIGIT;
if((a[i] = b[i] - borrow) > (BN_MAX_DIGIT - borrow)) {
borrow = 1;
} else {
borrow = 0;
}
if((a[i] -= rl) > (BN_MAX_DIGIT - rl)) {
borrow++;
}
borrow += rh;
}
return borrow;
}
static uint32_t bn_digit_bits(bn_t a)
{
uint32_t i;
for(i=0; i<BN_DIGIT_BITS; i++) {
if(a == 0) break;
a >>= 1;
}
return i;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化