~apreiml/bigc

b69533c723ac4f87053949af867d9149fa664d4e — Armin Preiml 1 year, 11 months ago dd847ab
a
3 files changed, 42 insertions(+), 12 deletions(-)

M crypto/bigint/+test/arithm.ha
M crypto/bigint/arithm.ha
M crypto/bigint/util.ha
M crypto/bigint/+test/arithm.ha => crypto/bigint/+test/arithm.ha +19 -0
@@ 107,3 107,22 @@ use fmt;
	free(t1);
	free(t2);
};

@test fn modpow_opt() void = {
	let m = fromhex("87654321");
	let x = fromhexmod("00f03202", m);

	let e: [_]u8 = [0x00, 0x00, 0xc1, 0xf4];
	const m0i = ninv31(m[1]);

	let tmp = fromhex("0000000000000000");

	modpow_opt(x, e, m, m0i, tmp, len(tmp));

	fmt::println("x:", tohex(x))!;
	assert(equalshex(x, "3de073fc"));

	free(m);
	free(x);
	free(tmp);
};

M crypto/bigint/arithm.ha => crypto/bigint/arithm.ha +17 -1
@@ 377,10 377,24 @@ fn ccopy(ctl: u32, dst: []u8, src: const []u8) void = {
	};
};

// Compute a modular exponentiation. x[] MUST be an integer modulo m[]
// (same announced bit length, lower value). m[] MUST be odd. The
// exponent is in big-endian unsigned notation, over 'elen' bytes. The
// "m0i" parameter is equal to -(1/m0) mod 2^31, where m0 is the least
// significant value word of m[] (this works only if m[] is an odd
// integer). The tmp[] array is used for temporaries, and has size
// 'twlen' words; it must be large enough to accommodate at least two
// temporary values with the same size as m[] (including the leading
// "bit length" word). If there is room for more temporaries, then this
// function may use the extra room for window-based optimisation,
// resulting in faster computations.
//
// Returned value is 1 on success, 0 on error. An error is reported if
// THE PROVIDED TMP[] ARRAY IS TOO SHORT.
// TODO figure out why redundant modpow?
fn modpow_opt(
	x: []word,
	e: []u8, // TODO const?
	elen: size, // TODO
	m: const []word,
	m0i: u32,
	tmp: []word,


@@ 434,6 448,8 @@ fn modpow_opt(
	x[(m[0] + 31) >> 5] = 1;
	muladd_small(x, 0, m);

	let elen = len(e);

	// We process bits from most to least significant. At each
	// loop iteration, we have acc_len bits in acc.
	let acc: word = 0;

M crypto/bigint/util.ha => crypto/bigint/util.ha +6 -11
@@ 107,19 107,14 @@ fn iszero(x: []word) u32 = {
};

@test fn iszero() void = {
	let x: [_]u8 = [0x21, 0x00, 0x32, 0xa0];
	let y: [_]u8 = [0x00, 0x00, 0x00, 0x00];
	let x = fromhex("210032a0");
	let y = fromhex("00000000");

	let bx: [4 * 8 / BITSIZE + 2]word = [0...];
	let by: [4 * 8 / BITSIZE + 2]word = [0...];
	assert(iszero(x) == 0);
	assert(iszero(y) == 1);

	encode(bx, x);
	encode(by, y);

	dn(bx, "bx");
	dn(by, "by");
	assert(iszero(bx) == 0);
	assert(iszero(by) == 1);
	free(x);
	free(y);
};