def crypto_scalarmult_curve25519_tweet(q, n, p): '''int crypto_scalarmult_curve25519_tweet(u8*q, const u8*n, const u8*p)''' z = IntArray(u8, size=32) x = IntArray(i64, size=80) r = i64() a = gf() b = gf() c = gf() d = gf() e = gf() f = gf() for i in range(31): z[i] = n[i] z[31] = (n[31] & 127) | 64 z[0] &= 248 unpack25519(x, p) for i in range(16): b[i] = x[i] d[i] = a[i] = c[i] = 0 a[0] = d[0] = 1 for i in range(254, -1, -1): r = (z[i >> 3] >> (i & 7)) & 1 sel25519(a, b, r) sel25519(c, d, r) A(e, a, c) Z(a, a, c) A(c, b, d) Z(b, b, d) S(d, e) S(f, a) M(a, c, a) M(c, b, e) A(e, a, c) Z(a, a, c) S(b, a) Z(c, d, f) M(a, c, _121665) A(a, a, d) M(c, c, a) M(a, d, f) M(d, b, x) S(b, e) sel25519(a, b, r) sel25519(c, d, r) for i in range(16): x[i + 16] = a[i] x[i + 32] = c[i] x[i + 48] = b[i] x[i + 64] = d[i] x[32:] = inv25519(x[32:], x[32:]) x[16:] = M(x[16:], x[16:], x[32:]) pack25519(q, x[16:]) return 0
def crypto_stream_salsa20_tweet_xor(c, m, b, n, k): '''int crypto_stream_salsa20_tweet_xor(u8*c, const u8*m, u64 b, const u8*n, const u8*k)''' z = IntArray(u8, size=16) x = IntArray(u8, size=64) if not b: return 0 for i in range(8): z[i] = n[i] c_off = 0 m_off = 0 while b >= 64: crypto_core_salsa20_tweet(x, z, k, sigma) for i in range(64): c[i + c_off] = (m[i + m_off] if m else 0) ^ x[i] u = u32(1) for i in range(8, 16): u += u32(z[i]) z[i] = u u >>= 8 b -= 64 c_off += 64 if m: m_off += 64 if b: crypto_core_salsa20_tweet(x, z, k, sigma) for i in range(b): c[i + c_off] = (m[i + m_off] if m else 0) ^ x[i] return 0
def crypto_hash_sha512_tweet(out, m, n): '''int crypto_hash_sha512_tweet(u8*out, const u8*m, u64 n)''' h = IntArray(u8, size=64) x = IntArray(u8, size=256) b = u64(n) for i in range(64): h[i] = iv[i] crypto_hashblocks_sha512_tweet(h, m, n) m_off = n n &= 127 m_off -= n x[:256] = 256 * [u8()] for i in range(n): x[i] = m[i + m_off] x[n] = 128 n = 256 - 128 * (n < 112) x[n - 9] = b >> 61 x[n - 8:] = ts64(x[n - 8:], b << 3) crypto_hashblocks_sha512_tweet(h, x, n) for i in range(64): out[i] = h[i] return 0
def neq25519(a, b): '''int neq25519(const gf a, const gf b)''' c = IntArray(u8, size=32) d = IntArray(u8, size=32) pack25519(c, a) pack25519(d, b) return crypto_verify_32_tweet(c, d)
def reduce(r): '''void reduce(u8*r)''' x = IntArray(i64, size=64) for i in range(64): x[i] = u64(r[i]) r[:64] = 64 * [u8()] modL(r, x)
def crypto_sign_ed25519_tweet(sm, smlen, m, n, sk): '''int crypto_sign_ed25519_tweet(u8*sm, u64*smlen, const u8*m, u64 n, const u8*sk)''' d = IntArray(u8, size=64) h = IntArray(u8, size=64) r = IntArray(u8, size=64) x = IntArray(i64, size=64) p = [gf() for i in range(4)] crypto_hash_sha512_tweet(d, sk, 32) d[0] &= 248 d[31] &= 127 d[31] |= 64 # There is no (simple?) way to return this argument's value back to the # user in python. Rather than redefining the return value of this function # it is better to advise the user that ``smlen`` does not work as it does # in the C implementation and that its value will be equal to ``n + 64``. smlen = n + 64 for i in range(n): sm[64 + i] = m[i] for i in range(32): sm[32 + i] = d[32 + i] crypto_hash_sha512_tweet(r, sm[32:], n + 32) reduce(r) scalarbase(p, r) pack(sm, p) for i in range(32): sm[i + 32] = sk[i + 32] crypto_hash_sha512_tweet(h, sm, n + 64) reduce(h) for i in range(64): x[i] = 0 for i in range(32): x[i] = u64(r[i]) for i in range(32): for j in range(32): x[i + j] += h[i] * u64(d[j]) sm[32:] = modL(sm[32:], x) return 0
def crypto_secretbox_xsalsa20poly1305_tweet_open(m, c, d, n, k): '''int crypto_secretbox_xsalsa20poly1305_tweet_open(u8*m, const u8*c, u64 d, const u8*n, const u8*k)''' x = IntArray(u8, size=32) if d < 32: return -1 crypto_stream_xsalsa20_tweet(x, 32, n, k) if crypto_onetimeauth_poly1305_tweet_verify(c[16:], c[32:], d - 32, x) != 0: return -1 crypto_stream_xsalsa20_tweet_xor(m, c, d, n, k) m[:32] = 32 * [u8()] return 0
def core(out, in_, k, c, h): '''void core(u8*out, const u8*in, const u8*k, const u8*c, int h)''' w = IntArray(u32, size=16) x = IntArray(u32, size=16) y = IntArray(u32, size=16) t = IntArray(u32, size=4) for i in range(4): x[5 * i] = ld32(c[4 * i:]) x[1 + i] = ld32(k[4 * i:]) x[6 + i] = ld32(in_[4 * i:]) x[11 + i] = ld32(k[16 + 4 * i:]) for i in range(16): y[i] = x[i] for i in range(20): for j in range(4): for m in range(4): t[m] = x[(5 * j + 4 * m) % 16] t[1] ^= L32(t[0] + t[3], 7) t[2] ^= L32(t[1] + t[0], 9) t[3] ^= L32(t[2] + t[1], 13) t[0] ^= L32(t[3] + t[2], 18) for m in range(4): w[4 * j + (j + m) % 4] = t[m] for m in range(16): x[m] = w[m] if h: for i in range(16): x[i] += y[i] for i in range(4): x[5 * i] -= ld32(c[4 * i:]) x[6 + i] -= ld32(in_[4 * i:]) for i in range(4): out[4 * i:] = st32(out[4 * i:], x[5 * i]) out[16 + 4 * i:] = st32(out[16 + 4 * i:], x[6 + i]) else: for i in range(16): out[4 * i:] = st32(out[4 * i:], x[i] + y[i])
def crypto_hashblocks_sha512_tweet(x, m, n): '''int crypto_hashblocks_sha512_tweet(u8*x, const u8*m, u64 n)''' z = IntArray(u64, size=8) b = IntArray(u64, size=8) a = IntArray(u64, size=8) w = IntArray(u64, size=16) t = u64() for i in range(8): z[i] = a[i] = dl64(x[8 * i:]) m_off = 0 while n >= 128: for i in range(16): w[i] = dl64(m[8 * i + m_off:]) for i in range(80): for j in range(8): b[j] = a[j] t = a[7] + Sigma1(a[4]) + Ch(a[4], a[5], a[6]) + K[i] + w[i % 16] b[7] = t + Sigma0(a[0]) + Maj(a[0], a[1], a[2]) b[3] += t for j in range(8): a[(j + 1) % 8] = b[j] if i % 16 == 15: for j in range(16): w[j] += w[(j + 9) % 16] + sigma0(w[(j + 1) % 16]) + sigma1( w[(j + 14) % 16]) for i in range(8): a[i] += z[i] z[i] = a[i] m_off += 128 n -= 128 for i in range(8): x[8 * i:] = ts64(x[8 * i:], z[i]) return n
def crypto_sign_ed25519_tweet_open(m, mlen, sm, n, pk): '''int crypto_sign_ed25519_tweet_open(u8*m, u64*mlen, const u8*sm, u64 n, const u8*pk)''' t = IntArray(u8, size=32) h = IntArray(u8, size=64) p = [gf() for i in range(4)] q = [gf() for i in range(4)] mlen = -1 if n < 64: return -1 if unpackneg(q, pk): return -1 for i in range(n): m[i] = sm[i] for i in range(32): m[i + 32] = pk[i] crypto_hash_sha512_tweet(h, m, n) reduce(h) scalarmult(p, q, h) scalarbase(q, sm[32:]) add(p, q) pack(t, p) n -= 64 if crypto_verify_32_tweet(sm, t): for i in range(n): m[i] = 0 return -1 for i in range(n): m[i] = sm[i + 64] # There is no (simple?) way to return this argument's value back to the # user in python. Rather than redefining the return value of this function # it is better to advise the user that ``mlen`` does not work as it does in # the C implementation and that its value will be equal to ``-1`` if ``n < # 64`` or decryption fails and ``n - 64`` otherwise. mlen = n return 0
def M(o, a, b): '''void M(gf o, const gf a, const gf b)''' t = IntArray(i64, size=31) for i in range(16): for j in range(16): t[i + j] += a[i] * b[j] for i in range(15): t[i] += 38 * t[i + 16] for i in range(16): o[i] = t[i] car25519(o) car25519(o) return o
def crypto_sign_ed25519_tweet_keypair(pk, sk): '''int crypto_sign_ed25519_tweet_keypair(u8*pk, u8*sk)''' d = IntArray(u8, size=64) p = [gf() for i in range(4)] randombytes(sk, 32) crypto_hash_sha512_tweet(d, sk, 32) d[0] &= 248 d[31] &= 127 d[31] |= 64 scalarbase(p, d) pack(pk, p) for i in range(32): sk[32 + i] = pk[i] return 0
def crypto_box_curve25519xsalsa20poly1305_tweet_open(m, c, d, n, y, x): '''int crypto_box_curve25519xsalsa20poly1305_tweet_open(u8*m, const u8*c, u64 d, const u8*n, const u8*y, const u8*x)''' k = IntArray(u8, size=32) crypto_box_curve25519xsalsa20poly1305_tweet_beforenm(k, y, x) return crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm( m, c, d, n, k)
def crypto_box_curve25519xsalsa20poly1305_tweet_beforenm(k, y, x): '''int crypto_box_curve25519xsalsa20poly1305_tweet_beforenm(u8*k, const u8*y, const u8*x)''' s = IntArray(u8, size=32) crypto_scalarmult_curve25519_tweet(s, x, y) return crypto_core_hsalsa20_tweet(k, _0, s, sigma)
def __init__(self, init=()): IntArray.__init__(self, i64, init=init, size=16)
def crypto_stream_salsa20_tweet(c, d, n, k): '''int crypto_stream_salsa20_tweet(u8*c, u64 d, const u8*n, const u8*k)''' return crypto_stream_salsa20_tweet_xor(c, IntArray(u8), d, n, k)
def crypto_stream_xsalsa20_tweet_xor(c, m, d, n, k): '''int crypto_stream_xsalsa20_tweet_xor(u8*c, const u8*m, u64 d, const u8*n, const u8*k)''' s = IntArray(u8, size=32) crypto_core_hsalsa20_tweet(s, n, k, sigma) return crypto_stream_salsa20_tweet_xor(c, m, d, n[16:], s)
def crypto_onetimeauth_poly1305_tweet_verify(h, m, n, k): '''int crypto_onetimeauth_poly1305_tweet_verify(const u8*h, const u8*m, u64 n, const u8*k)''' x = IntArray(u8, size=16) crypto_onetimeauth_poly1305_tweet(x, m, n, k) return crypto_verify_16_tweet(h, x)
def crypto_onetimeauth_poly1305_tweet(out, m, n, k): '''int crypto_onetimeauth_poly1305_tweet(u8*out, const u8*m, u64 n, const u8*k)''' s = u32() u = u32() x = IntArray(u32, size=17) r = IntArray(u32, size=17) h = IntArray(u32, size=17) c = IntArray(u32, size=17) g = IntArray(u32, size=17) for j in range(16): r[j] = k[j] r[3] &= 15 r[4] &= 252 r[7] &= 15 r[8] &= 252 r[11] &= 15 r[12] &= 252 r[15] &= 15 while n > 0: c[:17] = 17 * [u32()] for j in range(16): if j >= n: j -= 1 break c[j] = m[j] j += 1 c[j] = 1 m = m[j:] n -= j add1305(h, c) for i in range(17): x[i] = 0 for j in range(17): x[i] += h[j] * (r[i - j] if j <= i else 320 * r[i + 17 - j]) for i in range(17): h[i] = x[i] u = 0 for j in range(16): u += h[j] h[j] = u & 255 u >>= 8 u += h[16] h[16] = u & 3 u = 5 * (u >> 2) for j in range(16): u += h[j] h[j] = u & 255 u >>= 8 u += h[16] h[16] = u for j in range(17): g[j] = h[j] add1305(h, minusp) s = -(h[16] >> 7) for j in range(17): h[j] ^= s & (g[j] ^ h[j]) for j in range(16): c[j] = k[j + 16] c[16] = 0 add1305(h, c) for j in range(16): out[j] = h[j] return 0
def par25519(a): '''u8 par25519(const gf a)''' d = IntArray(u8, size=32) pack25519(d, a) return d[0] & 1
class gf(IntArray): def __init__(self, init=()): IntArray.__init__(self, i64, init=init, size=16) def randombytes(c, s): ''' insert s random bytes into c ''' if lt_py3: c[:s] = bytearray(os.urandom(s)) else: c[:s] = os.urandom(s) _0 = IntArray(u8, size=16) _9 = IntArray(u8, size=32, init=[9]) gf0 = gf() gf1 = gf([1]) _121665 = gf([0xDB41, 1]) D = gf([ 0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203 ]) D2 = gf([ 0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406 ]) X = gf([ 0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c,