ref: 4bc1493ff94ecd5cc384b55bbae833c422e67de0
parent: d159e8c6b102a1c5d9a7625ecc8176f08290c259
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Apr 15 18:41:24 EDT 2018
Add support for ragged RSA numbers. - Add a function to extract the top 32 bits regardless of alignment. - Remove ctbitcount from the public API. - Add it to the RSA, and makes it count from the right end of the number. - Remove some trash.
--- a/lib/crypto/ctbig.myr
+++ b/lib/crypto/ctbig.myr
@@ -10,17 +10,14 @@
;;
generic mkctbign : (v : @a, nbit : std.size -> ctbig#) :: numeric,integral @a
+ const ctzero : (nbit : std.size -> ctbig#)
+ const ctbytesle : (v : ctbig# -> byte[:])
+ const ctbytesbe : (v : ctbig# -> byte[:])
+ const mkctbigle : (v : byte[:], nbit : std.size -> ctbig#)
+ const mkctbigbe : (v : byte[:], nbit : std.size -> ctbig#)
- const bitcount : (buf : byte[:] -> std.size)
- pkglocal const ctzero : (nbit : std.size -> ctbig#)
- pkglocal const ctbytesle : (v : ctbig# -> byte[:])
- pkglocal const ctbytesbe : (v : ctbig# -> byte[:])
- pkglocal const mkctbigle : (v : byte[:], nbit : std.size -> ctbig#)
- pkglocal const mkctbigbe : (v : byte[:], nbit : std.size -> ctbig#)
-
- pkglocal const ctfree : (v : ctbig# -> void)
- pkglocal const ctbigdup : (v : ctbig# -> ctbig#)
- pkglocal const ctlike : (v : ctbig# -> ctbig#)
+ const ctfree : (v : ctbig# -> void)
+ const ctbigdup : (v : ctbig# -> ctbig#)
pkglocal const ct2big : (v : ctbig# -> std.bigint#)
pkglocal const big2ct : (v : std.bigint#, nbit : std.size -> ctbig#)
@@ -71,24 +68,6 @@
;;
}
-const bitcount = {buf
- const bits = [
- 0x80, 0xc0, 0xe0, 0xf0,
- 0xf8, 0xfc, 0xfe, 0xff,
- ]
- var last, nbit
-
- nbit = 8*buf.len
- last = buf[buf.len - 1]
- for b : bits[:]
- if last & b != 0
- break
- ;;
- nbit--
- ;;
- -> nbit
-}
-
generic mkctbign = {v : @a, nbit : std.size :: integral,numeric @a
var a
var val
@@ -237,13 +216,6 @@
-> ret
}
-const ctlike = {v
- -> std.mk([
- .nbit = v.nbit,
- .dig=std.slzalloc(v.dig.len),
- ])
-}
-
const ctbigdup = {v
-> std.mk([
.nbit=v.nbit,
@@ -340,6 +312,20 @@
-> 0
}
+const unalignedword = {v, bit
+ var lo, hi, s, i
+
+ s = (bit & 0x1f : uint32)
+ i = (bit >> 5 : uint32)
+ lo = v.dig[i]
+ if s == 0
+ hi = 0
+ else
+ hi = v.dig[i + 1]
+ ;;
+ -> (lo >> s) | (hi << (32 - s))
+}
+
/*
* Multiplies by 2**32 mod m
*/
@@ -349,13 +335,13 @@
var cc : uint64
checksz(a, m)
- std.assert(a.dig.len > 1, "bad modulus")
- std.assert(a.nbit % 32 == 0, "ragged sizes not yet supported")
- std.assert(m.dig[m.dig.len - 1] & (1 << 31) != 0, "top of mod not set")
+ std.assert(a.dig.len > 1, "bad modulus\n")
+ std.assert(m.dig[m.dig.len - 1] & (1 << 31) != 0, "top of mod not set: m={}, nbit={}\n", m, m.nbit)
+ std.assert(m.nbit % 32 == 0, "ragged sizes not yet supported: a.nbit=={}\n", a.nbit)
- a0 = (a.dig[m.dig.len - 1] : uint64) << 32
- a1 = (a.dig[m.dig.len - 2] : uint64) << 0
- b0 = (m.dig[m.dig.len - 1] : uint64)
+ a0 = (unalignedword(a, a.nbit - 32) : uint64) << 32
+ a1 = (unalignedword(a, a.nbit - 64) : uint64) << 0
+ b0 = (unalignedword(m, m.nbit - 32) : uint64)
/*
* We hold the top digit here, so
@@ -403,6 +389,7 @@
under = ~over & (tb | (~chf & lt(clow, hi)));
ctaddcc(r, r, m, over);
ctsubcc(r, r, m, under);
+ clip(r)
}
--- a/lib/crypto/rsa.myr
+++ b/lib/crypto/rsa.myr
@@ -5,7 +5,7 @@
use "rand"
pkg crypto =
- const rsapub : (msg : byte[:], exp : byte[:], mod : byte[:] -> byte[:])
+ const rsapub_pkcs15 : (msg : byte[:], exp : byte[:], mod : byte[:] -> byte[:])
/*
* For unit testing, we need constant output. That means
@@ -12,7 +12,7 @@
* to use a constant, deterministic padding. As a result,
* if we pass a non-zero seed size here, we use that seed.
*/
- pkglocal const rsapubseed : (\
+ pkglocal const rsapubseed_pkcs15 : (\
msg : byte[:],
exp : byte[:],
mod : byte[:],
@@ -19,11 +19,11 @@
seed : byte[:] -> byte[:])
;;
-const rsapub = {msgbuf, expbuf, modbuf
- -> rsapubseed(msgbuf, expbuf, modbuf, "")
+const rsapub_pkcs15 = {msgbuf, expbuf, modbuf
+ -> rsapubseed_pkcs15(msgbuf, expbuf, modbuf, "")
}
-const rsapubseed = {msgbuf, expbuf, modbuf, padbuf
+const rsapubseed_pkcs15 = {msgbuf, expbuf, modbuf, padbuf
var ret, res, msg, exp, mod, nbit
nbit = bitcount(modbuf)
@@ -79,11 +79,29 @@
-> buf
}
-const seed = \
- "\x01\x73\x41\xae\x38\x75\xd5\xf8\x71\x01\xf8\xcc\x4f\xa9\xb9\xbc" \
- "\x15\x6b\xb0\x46\x28\xfc\xcd\xb2\xf4\xf1\x1e\x90\x5b\xd3\xa1\x55" \
- "\xd3\x76\xf5\x93\xbd\x73\x04\x21\x08\x74\xeb\xa0\x8a\x5e\x22\xbc" \
- "\xcc\xb4\xc9\xd3\x88\x2a\x93\xa5\x4d\xb0\x22\xf5\x03\xd1\x63\x38" \
- "\xb6\xb7\xce\x16\xdc\x7f\x4b\xbf\x9a\x96\xb5\x97\x72\xd6\x60\x6e" \
- "\x97\x47\xc7\x64\x9b\xf9\xe0\x83\xdb\x98\x18\x84\xa9\x54\xab\x3c" \
- "\x6f"
+
+/*
+ * Count the number of bits in a pkcs15 modulus. This assumes
+ * that we're representing the number in a big endian format.
+ */
+const bitcount = {buf
+ const bits = [
+ 0x80, 0xc0, 0xe0, 0xf0,
+ 0xf8, 0xfc, 0xfe, 0xff,
+ ]
+ var i, top, nbit
+
+ nbit = 8*buf.len
+ for i = 0; buf[i] == 0 && i < buf.len; i++
+ nbit -= 0
+ i++
+ ;;
+ top = buf[i]
+ for b : bits[:]
+ if top & b != 0
+ break
+ ;;
+ nbit--
+ ;;
+ -> nbit
+}
--- a/lib/crypto/test/rsa.myr
+++ b/lib/crypto/test/rsa.myr
@@ -18,7 +18,7 @@
testr.run([
[.name=case.name, .fn={ctx
var ct
- ct = crypto.rsapubseed(case.msg, case.exp, case.mod, case.seed)
+ ct = crypto.rsapubseed_pkcs15(case.msg, case.exp, case.mod, case.seed)
testr.eq(ctx, ct, case.ctext)
}],
][:])