1949 lines
67 KiB
Nim
1949 lines
67 KiB
Nim
# Nim-Libp2p
|
|
# Copyright (c) 2023 Status Research & Development GmbH
|
|
# Licensed under either of
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
|
# at your option.
|
|
# This file may not be copied, modified, or distributed except according to
|
|
# those terms.
|
|
|
|
## This module implements ED25519.
|
|
## This code is a port of the public domain, "ref10" implementation of ed25519
|
|
## from SUPERCOP.
|
|
|
|
when (NimMajor, NimMinor) < (1, 4):
|
|
{.push raises: [Defect].}
|
|
else:
|
|
{.push raises: [].}
|
|
|
|
import bearssl/rand
|
|
import constants
|
|
import nimcrypto/[hash, sha2]
|
|
# We use `ncrutils` for constant-time hexadecimal encoding/decoding procedures.
|
|
import nimcrypto/utils as ncrutils
|
|
import stew/[results, ctops]
|
|
export results
|
|
|
|
# This workaround needed because of some bugs in Nim Static[T].
|
|
export hash, sha2, rand
|
|
|
|
const
|
|
EdPrivateKeySize* = 64
|
|
## Size in octets (bytes) of serialized ED25519 private key.
|
|
EdPublicKeySize* = 32
|
|
## Size in octets (bytes) of serialized ED25519 public key.
|
|
EdSignatureSize* = 64
|
|
## Size in octets (bytes) of serialized ED25519 signature.
|
|
|
|
type
|
|
EdPrivateKey* = object
|
|
data*: array[EdPrivateKeySize, byte]
|
|
|
|
EdPublicKey* = object
|
|
data*: array[EdPublicKeySize, byte]
|
|
|
|
EdSignature* = object
|
|
data*: array[EdSignatureSize, byte]
|
|
|
|
EdKeyPair* = object
|
|
seckey*: EdPrivateKey
|
|
pubkey*: EdPublicKey
|
|
|
|
EdError* = enum
|
|
EdIncorrectError
|
|
|
|
proc `-`(x: uint32): uint32 {.inline.} =
|
|
result = (0xFFFF_FFFF'u32 - x) + 1'u32
|
|
|
|
proc `-`(x: uint8): uint8 {.inline.} =
|
|
result = (0xFF'u8 - x) + 1'u8
|
|
|
|
proc fe0(h: var Fe) =
|
|
h[0] = 0; h[1] = 0; h[2] = 0; h[3] = 0; h[4] = 0
|
|
h[5] = 0; h[6] = 0; h[7] = 0; h[8] = 0; h[9] = 0
|
|
|
|
proc fe1(h: var Fe) =
|
|
h[0] = 1; h[1] = 0; h[2] = 0; h[3] = 0; h[4] = 0
|
|
h[5] = 0; h[6] = 0; h[7] = 0; h[8] = 0; h[9] = 0
|
|
|
|
proc feAdd(h: var Fe, f, g: Fe) =
|
|
var f0 = f[0]; var f1 = f[1]; var f2 = f[2]; var f3 = f[3]; var f4 = f[4]
|
|
var f5 = f[5]; var f6 = f[6]; var f7 = f[7]; var f8 = f[8]; var f9 = f[9]
|
|
var g0 = g[0]; var g1 = g[1]; var g2 = g[2]; var g3 = g[3]; var g4 = g[4]
|
|
var g5 = g[5]; var g6 = g[6]; var g7 = g[7]; var g8 = g[8]; var g9 = g[9]
|
|
var h0 = f0 + g0
|
|
var h1 = f1 + g1
|
|
var h2 = f2 + g2
|
|
var h3 = f3 + g3
|
|
var h4 = f4 + g4
|
|
var h5 = f5 + g5
|
|
var h6 = f6 + g6
|
|
var h7 = f7 + g7
|
|
var h8 = f8 + g8
|
|
var h9 = f9 + g9
|
|
h[0] = h0
|
|
h[1] = h1
|
|
h[2] = h2
|
|
h[3] = h3
|
|
h[4] = h4
|
|
h[5] = h5
|
|
h[6] = h6
|
|
h[7] = h7
|
|
h[8] = h8
|
|
h[9] = h9
|
|
|
|
proc feSub(h: var Fe, f, g: Fe) =
|
|
var f0 = f[0]; var f1 = f[1]; var f2 = f[2]; var f3 = f[3]; var f4 = f[4]
|
|
var f5 = f[5]; var f6 = f[6]; var f7 = f[7]; var f8 = f[8]; var f9 = f[9]
|
|
var g0 = g[0]; var g1 = g[1]; var g2 = g[2]; var g3 = g[3]; var g4 = g[4]
|
|
var g5 = g[5]; var g6 = g[6]; var g7 = g[7]; var g8 = g[8]; var g9 = g[9]
|
|
var h0 = f0 - g0
|
|
var h1 = f1 - g1
|
|
var h2 = f2 - g2
|
|
var h3 = f3 - g3
|
|
var h4 = f4 - g4
|
|
var h5 = f5 - g5
|
|
var h6 = f6 - g6
|
|
var h7 = f7 - g7
|
|
var h8 = f8 - g8
|
|
var h9 = f9 - g9
|
|
h[0] = h0
|
|
h[1] = h1
|
|
h[2] = h2
|
|
h[3] = h3
|
|
h[4] = h4
|
|
h[5] = h5
|
|
h[6] = h6
|
|
h[7] = h7
|
|
h[8] = h8
|
|
h[9] = h9
|
|
|
|
proc feCmov(f: var Fe, g: Fe, b: uint32) =
|
|
var f0 = f[0]; var f1 = f[1]; var f2 = f[2]; var f3 = f[3]; var f4 = f[4]
|
|
var f5 = f[5]; var f6 = f[6]; var f7 = f[7]; var f8 = f[8]; var f9 = f[9]
|
|
var g0 = g[0]; var g1 = g[1]; var g2 = g[2]; var g3 = g[3]; var g4 = g[4]
|
|
var g5 = g[5]; var g6 = g[6]; var g7 = g[7]; var g8 = g[8]; var g9 = g[9]
|
|
var x0 = f0 xor g0
|
|
var x1 = f1 xor g1
|
|
var x2 = f2 xor g2
|
|
var x3 = f3 xor g3
|
|
var x4 = f4 xor g4
|
|
var x5 = f5 xor g5
|
|
var x6 = f6 xor g6
|
|
var x7 = f7 xor g7
|
|
var x8 = f8 xor g8
|
|
var x9 = f9 xor g9
|
|
var bc = -b
|
|
x0 = x0 and cast[int32](bc)
|
|
x1 = x1 and cast[int32](bc)
|
|
x2 = x2 and cast[int32](bc)
|
|
x3 = x3 and cast[int32](bc)
|
|
x4 = x4 and cast[int32](bc)
|
|
x5 = x5 and cast[int32](bc)
|
|
x6 = x6 and cast[int32](bc)
|
|
x7 = x7 and cast[int32](bc)
|
|
x8 = x8 and cast[int32](bc)
|
|
x9 = x9 and cast[int32](bc)
|
|
f[0] = f0 xor x0
|
|
f[1] = f1 xor x1
|
|
f[2] = f2 xor x2
|
|
f[3] = f3 xor x3
|
|
f[4] = f4 xor x4
|
|
f[5] = f5 xor x5
|
|
f[6] = f6 xor x6
|
|
f[7] = f7 xor x7
|
|
f[8] = f8 xor x8
|
|
f[9] = f9 xor x9
|
|
|
|
proc feCopy(h: var Fe, f: Fe) =
|
|
var f0 = f[0]; var f1 = f[1]; var f2 = f[2]; var f3 = f[3]; var f4 = f[4]
|
|
var f5 = f[5]; var f6 = f[6]; var f7 = f[7]; var f8 = f[8]; var f9 = f[9]
|
|
h[0] = f0
|
|
h[1] = f1
|
|
h[2] = f2
|
|
h[3] = f3
|
|
h[4] = f4
|
|
h[5] = f5
|
|
h[6] = f6
|
|
h[7] = f7
|
|
h[8] = f8
|
|
h[9] = f9
|
|
|
|
proc load_3(inp: openArray[byte]): uint64 =
|
|
result = cast[uint64](inp[0])
|
|
result = result or (cast[uint64](inp[1]) shl 8)
|
|
result = result or (cast[uint64](inp[2]) shl 16)
|
|
|
|
proc load_4(inp: openArray[byte]): uint64 =
|
|
result = cast[uint64](inp[0])
|
|
result = result or (cast[uint64](inp[1]) shl 8)
|
|
result = result or (cast[uint64](inp[2]) shl 16)
|
|
result = result or (cast[uint64](inp[3]) shl 24)
|
|
|
|
proc feFromBytes(h: var Fe, s: openArray[byte]) =
|
|
var c0, c1, c2, c3, c4, c5, c6, c7, c8, c9: int64
|
|
|
|
var h0 = cast[int64](load_4(s.toOpenArray(0, 3)))
|
|
var h1 = cast[int64](load_3(s.toOpenArray(4, 6))) shl 6
|
|
var h2 = cast[int64](load_3(s.toOpenArray(7, 9))) shl 5
|
|
var h3 = cast[int64](load_3(s.toOpenArray(10, 12))) shl 3
|
|
var h4 = cast[int64](load_3(s.toOpenArray(13, 15))) shl 2
|
|
var h5 = cast[int64](load_4(s.toOpenArray(16, 19)))
|
|
var h6 = cast[int64](load_3(s.toOpenArray(20, 22))) shl 7
|
|
var h7 = cast[int64](load_3(s.toOpenArray(23, 25))) shl 5
|
|
var h8 = cast[int64](load_3(s.toOpenArray(26, 28))) shl 4
|
|
var h9 = (cast[int64](load_3(s.toOpenArray(29, 31))) and 8388607'i32) shl 2
|
|
|
|
c9 = ashr((h9 + (1'i64 shl 24)), 25); h0 = h0 + (c9 * 19); h9 -= (c9 shl 25)
|
|
c1 = ashr((h1 + (1'i64 shl 24)), 25); h2 = h2 + c1; h1 -= (c1 shl 25)
|
|
c3 = ashr((h3 + (1'i64 shl 24)), 25); h4 = h4 + c3; h3 -= (c3 shl 25)
|
|
c5 = ashr((h5 + (1'i64 shl 24)), 25); h6 = h6 + c5; h5 -= (c5 shl 25)
|
|
c7 = ashr((h7 + (1'i64 shl 24)), 25); h8 = h8 + c7; h7 -= (c7 shl 25)
|
|
|
|
c0 = ashr((h0 + (1'i64 shl 25)), 26); h1 = h1 + c0; h0 -= (c0 shl 26)
|
|
c2 = ashr((h2 + (1'i64 shl 25)), 26); h3 = h3 + c2; h2 -= (c2 shl 26)
|
|
c4 = ashr((h4 + (1'i64 shl 25)), 26); h5 = h5 + c4; h4 -= (c4 shl 26)
|
|
c6 = ashr((h6 + (1'i64 shl 25)), 26); h7 = h7 + c6; h6 -= (c6 shl 26)
|
|
c8 = ashr((h8 + (1'i64 shl 25)), 26); h9 = h9 + c8; h8 -= (c8 shl 26)
|
|
|
|
h[0] = cast[int32](h0)
|
|
h[1] = cast[int32](h1)
|
|
h[2] = cast[int32](h2)
|
|
h[3] = cast[int32](h3)
|
|
h[4] = cast[int32](h4)
|
|
h[5] = cast[int32](h5)
|
|
h[6] = cast[int32](h6)
|
|
h[7] = cast[int32](h7)
|
|
h[8] = cast[int32](h8)
|
|
h[9] = cast[int32](h9)
|
|
|
|
proc feToBytes(s: var openArray[byte], h: Fe) =
|
|
var h0 = h[0]; var h1 = h[1]; var h2 = h[2]; var h3 = h[3]; var h4 = h[4]
|
|
var h5 = h[5]; var h6 = h[6]; var h7 = h[7]; var h8 = h[8]; var h9 = h[9]
|
|
var q, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9: int32
|
|
|
|
q = ashr((19 * h9 + (1'i32 shl 24)), 25)
|
|
q = ashr(h0 + q, 26)
|
|
q = ashr(h1 + q, 25)
|
|
q = ashr(h2 + q, 26)
|
|
q = ashr(h3 + q, 25)
|
|
q = ashr(h4 + q, 26)
|
|
q = ashr(h5 + q, 25)
|
|
q = ashr(h6 + q, 26)
|
|
q = ashr(h7 + q, 25)
|
|
q = ashr(h8 + q, 26)
|
|
q = ashr(h9 + q, 25)
|
|
|
|
h0 = h0 + 19 * q
|
|
|
|
c0 = ashr(h0, 26); h1 += c0; h0 -= c0 shl 26;
|
|
c1 = ashr(h1, 25); h2 += c1; h1 -= c1 shl 25;
|
|
c2 = ashr(h2, 26); h3 += c2; h2 -= c2 shl 26;
|
|
c3 = ashr(h3, 25); h4 += c3; h3 -= c3 shl 25;
|
|
c4 = ashr(h4, 26); h5 += c4; h4 -= c4 shl 26;
|
|
c5 = ashr(h5, 25); h6 += c5; h5 -= c5 shl 25;
|
|
c6 = ashr(h6, 26); h7 += c6; h6 -= c6 shl 26;
|
|
c7 = ashr(h7, 25); h8 += c7; h7 -= c7 shl 25;
|
|
c8 = ashr(h8, 26); h9 += c8; h8 -= c8 shl 26;
|
|
c9 = ashr(h9, 25); h9 -= c9 shl 25;
|
|
|
|
s[0] = cast[byte](ashr(h0, 0))
|
|
s[1] = cast[byte](ashr(h0, 8))
|
|
s[2] = cast[byte](ashr(h0, 16))
|
|
s[3] = cast[byte]((ashr(h0, 24) or (h1 shl 2)))
|
|
s[4] = cast[byte](ashr(h1, 6))
|
|
s[5] = cast[byte](ashr(h1, 14))
|
|
s[6] = cast[byte]((ashr(h1, 22) or (h2 shl 3)))
|
|
s[7] = cast[byte](ashr(h2, 5))
|
|
s[8] = cast[byte](ashr(h2, 13))
|
|
s[9] = cast[byte]((ashr(h2, 21) or (h3 shl 5)))
|
|
s[10] = cast[byte](ashr(h3, 3))
|
|
s[11] = cast[byte](ashr(h3, 11))
|
|
s[12] = cast[byte]((ashr(h3, 19) or (h4 shl 6)))
|
|
s[13] = cast[byte](ashr(h4, 2))
|
|
s[14] = cast[byte](ashr(h4, 10))
|
|
s[15] = cast[byte](ashr(h4, 18))
|
|
s[16] = cast[byte](ashr(h5, 0))
|
|
s[17] = cast[byte](ashr(h5, 8))
|
|
s[18] = cast[byte](ashr(h5, 16))
|
|
s[19] = cast[byte]((ashr(h5, 24) or (h6 shl 1)))
|
|
s[20] = cast[byte](ashr(h6, 7))
|
|
s[21] = cast[byte](ashr(h6, 15))
|
|
s[22] = cast[byte]((ashr(h6, 23) or (h7 shl 3)))
|
|
s[23] = cast[byte](ashr(h7, 5))
|
|
s[24] = cast[byte](ashr(h7, 13))
|
|
s[25] = cast[byte]((ashr(h7, 21) or (h8 shl 4)))
|
|
s[26] = cast[byte](ashr(h8, 4))
|
|
s[27] = cast[byte](ashr(h8, 12))
|
|
s[28] = cast[byte]((ashr(h8, 20) or (h9 shl 6)))
|
|
s[29] = cast[byte](ashr(h9, 2))
|
|
s[30] = cast[byte](ashr(h9, 10))
|
|
s[31] = cast[byte](ashr(h9, 18))
|
|
|
|
proc feMul(h: var Fe, f, g: Fe) =
|
|
var f0 = f[0]; var f1 = f[1]; var f2 = f[2]; var f3 = f[3]; var f4 = f[4]
|
|
var f5 = f[5]; var f6 = f[6]; var f7 = f[7]; var f8 = f[8]; var f9 = f[9]
|
|
var g0 = g[0]; var g1 = g[1]; var g2 = g[2]; var g3 = g[3]; var g4 = g[4]
|
|
var g5 = g[5]; var g6 = g[6]; var g7 = g[7]; var g8 = g[8]; var g9 = g[9]
|
|
var g1_19 = 19 * g1
|
|
var g2_19 = 19 * g2
|
|
var g3_19 = 19 * g3
|
|
var g4_19 = 19 * g4
|
|
var g5_19 = 19 * g5
|
|
var g6_19 = 19 * g6
|
|
var g7_19 = 19 * g7
|
|
var g8_19 = 19 * g8
|
|
var g9_19 = 19 * g9
|
|
var f1_2 = 2 * f1
|
|
var f3_2 = 2 * f3
|
|
var f5_2 = 2 * f5
|
|
var f7_2 = 2 * f7
|
|
var f9_2 = 2 * f9
|
|
var f0g0 = cast[int64](f0) * cast[int64](g0)
|
|
var f0g1 = cast[int64](f0) * cast[int64](g1)
|
|
var f0g2 = cast[int64](f0) * cast[int64](g2)
|
|
var f0g3 = cast[int64](f0) * cast[int64](g3)
|
|
var f0g4 = cast[int64](f0) * cast[int64](g4)
|
|
var f0g5 = cast[int64](f0) * cast[int64](g5)
|
|
var f0g6 = cast[int64](f0) * cast[int64](g6)
|
|
var f0g7 = cast[int64](f0) * cast[int64](g7)
|
|
var f0g8 = cast[int64](f0) * cast[int64](g8)
|
|
var f0g9 = cast[int64](f0) * cast[int64](g9)
|
|
var f1g0 = cast[int64](f1) * cast[int64](g0)
|
|
var f1g1_2 = cast[int64](f1_2) * cast[int64](g1)
|
|
var f1g2 = cast[int64](f1) * cast[int64](g2)
|
|
var f1g3_2 = cast[int64](f1_2) * cast[int64](g3)
|
|
var f1g4 = cast[int64](f1) * cast[int64](g4)
|
|
var f1g5_2 = cast[int64](f1_2) * cast[int64](g5)
|
|
var f1g6 = cast[int64](f1) * cast[int64](g6)
|
|
var f1g7_2 = cast[int64](f1_2) * cast[int64](g7)
|
|
var f1g8 = cast[int64](f1) * cast[int64](g8)
|
|
var f1g9_38 = cast[int64](f1_2) * cast[int64](g9_19)
|
|
var f2g0 = cast[int64](f2) * cast[int64](g0)
|
|
var f2g1 = cast[int64](f2) * cast[int64](g1)
|
|
var f2g2 = cast[int64](f2) * cast[int64](g2)
|
|
var f2g3 = cast[int64](f2) * cast[int64](g3)
|
|
var f2g4 = cast[int64](f2) * cast[int64](g4)
|
|
var f2g5 = cast[int64](f2) * cast[int64](g5)
|
|
var f2g6 = cast[int64](f2) * cast[int64](g6)
|
|
var f2g7 = cast[int64](f2) * cast[int64](g7)
|
|
var f2g8_19 = cast[int64](f2) * cast[int64](g8_19)
|
|
var f2g9_19 = cast[int64](f2) * cast[int64](g9_19)
|
|
var f3g0 = cast[int64](f3) * cast[int64](g0)
|
|
var f3g1_2 = cast[int64](f3_2) * cast[int64](g1)
|
|
var f3g2 = cast[int64](f3) * cast[int64](g2)
|
|
var f3g3_2 = cast[int64](f3_2) * cast[int64](g3)
|
|
var f3g4 = cast[int64](f3) * cast[int64](g4)
|
|
var f3g5_2 = cast[int64](f3_2) * cast[int64](g5)
|
|
var f3g6 = cast[int64](f3) * cast[int64](g6)
|
|
var f3g7_38 = cast[int64](f3_2) * cast[int64](g7_19)
|
|
var f3g8_19 = cast[int64](f3) * cast[int64](g8_19)
|
|
var f3g9_38 = cast[int64](f3_2) * cast[int64](g9_19)
|
|
var f4g0 = cast[int64](f4) * cast[int64](g0)
|
|
var f4g1 = cast[int64](f4) * cast[int64](g1)
|
|
var f4g2 = cast[int64](f4) * cast[int64](g2)
|
|
var f4g3 = cast[int64](f4) * cast[int64](g3)
|
|
var f4g4 = cast[int64](f4) * cast[int64](g4)
|
|
var f4g5 = cast[int64](f4) * cast[int64](g5)
|
|
var f4g6_19 = cast[int64](f4) * cast[int64](g6_19)
|
|
var f4g7_19 = cast[int64](f4) * cast[int64](g7_19)
|
|
var f4g8_19 = cast[int64](f4) * cast[int64](g8_19)
|
|
var f4g9_19 = cast[int64](f4) * cast[int64](g9_19)
|
|
var f5g0 = cast[int64](f5) * cast[int64](g0)
|
|
var f5g1_2 = cast[int64](f5_2) * cast[int64](g1)
|
|
var f5g2 = cast[int64](f5) * cast[int64](g2)
|
|
var f5g3_2 = cast[int64](f5_2) * cast[int64](g3)
|
|
var f5g4 = cast[int64](f5) * cast[int64](g4)
|
|
var f5g5_38 = cast[int64](f5_2) * cast[int64](g5_19)
|
|
var f5g6_19 = cast[int64](f5) * cast[int64](g6_19)
|
|
var f5g7_38 = cast[int64](f5_2) * cast[int64](g7_19)
|
|
var f5g8_19 = cast[int64](f5) * cast[int64](g8_19)
|
|
var f5g9_38 = cast[int64](f5_2) * cast[int64](g9_19)
|
|
var f6g0 = cast[int64](f6) * cast[int64](g0)
|
|
var f6g1 = cast[int64](f6) * cast[int64](g1)
|
|
var f6g2 = cast[int64](f6) * cast[int64](g2)
|
|
var f6g3 = cast[int64](f6) * cast[int64](g3)
|
|
var f6g4_19 = cast[int64](f6) * cast[int64](g4_19)
|
|
var f6g5_19 = cast[int64](f6) * cast[int64](g5_19)
|
|
var f6g6_19 = cast[int64](f6) * cast[int64](g6_19)
|
|
var f6g7_19 = cast[int64](f6) * cast[int64](g7_19)
|
|
var f6g8_19 = cast[int64](f6) * cast[int64](g8_19)
|
|
var f6g9_19 = cast[int64](f6) * cast[int64](g9_19)
|
|
var f7g0 = cast[int64](f7) * cast[int64](g0)
|
|
var f7g1_2 = cast[int64](f7_2) * cast[int64](g1)
|
|
var f7g2 = cast[int64](f7) * cast[int64](g2)
|
|
var f7g3_38 = cast[int64](f7_2) * cast[int64](g3_19)
|
|
var f7g4_19 = cast[int64](f7) * cast[int64](g4_19)
|
|
var f7g5_38 = cast[int64](f7_2) * cast[int64](g5_19)
|
|
var f7g6_19 = cast[int64](f7) * cast[int64](g6_19)
|
|
var f7g7_38 = cast[int64](f7_2) * cast[int64](g7_19)
|
|
var f7g8_19 = cast[int64](f7) * cast[int64](g8_19)
|
|
var f7g9_38 = cast[int64](f7_2) * cast[int64](g9_19)
|
|
var f8g0 = cast[int64](f8) * cast[int64](g0)
|
|
var f8g1 = cast[int64](f8) * cast[int64](g1)
|
|
var f8g2_19 = cast[int64](f8) * cast[int64](g2_19)
|
|
var f8g3_19 = cast[int64](f8) * cast[int64](g3_19)
|
|
var f8g4_19 = cast[int64](f8) * cast[int64](g4_19)
|
|
var f8g5_19 = cast[int64](f8) * cast[int64](g5_19)
|
|
var f8g6_19 = cast[int64](f8) * cast[int64](g6_19)
|
|
var f8g7_19 = cast[int64](f8) * cast[int64](g7_19)
|
|
var f8g8_19 = cast[int64](f8) * cast[int64](g8_19)
|
|
var f8g9_19 = cast[int64](f8) * cast[int64](g9_19)
|
|
var f9g0 = cast[int64](f9) * cast[int64](g0)
|
|
var f9g1_38 = cast[int64](f9_2) * cast[int64](g1_19)
|
|
var f9g2_19 = cast[int64](f9) * cast[int64](g2_19)
|
|
var f9g3_38 = cast[int64](f9_2) * cast[int64](g3_19)
|
|
var f9g4_19 = cast[int64](f9) * cast[int64](g4_19)
|
|
var f9g5_38 = cast[int64](f9_2) * cast[int64](g5_19)
|
|
var f9g6_19 = cast[int64](f9) * cast[int64](g6_19)
|
|
var f9g7_38 = cast[int64](f9_2) * cast[int64](g7_19)
|
|
var f9g8_19 = cast[int64](f9) * cast[int64](g8_19)
|
|
var f9g9_38 = cast[int64](f9_2) * cast[int64](g9_19)
|
|
var
|
|
c0, c1, c2, c3, c4, c5, c6, c7, c8, c9: int64
|
|
h0: int64 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 +
|
|
f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38
|
|
h1: int64 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 +
|
|
f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19
|
|
h2: int64 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 +
|
|
f7g5_38 + f8g4_19 + f9g3_38
|
|
h3: int64 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 +
|
|
f7g6_19 + f8g5_19 + f9g4_19
|
|
h4: int64 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 +
|
|
f7g7_38 + f8g6_19 + f9g5_38
|
|
h5: int64 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 +
|
|
f8g7_19 + f9g6_19
|
|
h6: int64 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 +
|
|
f7g9_38 + f8g8_19 + f9g7_38
|
|
h7: int64 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 +
|
|
f8g9_19 + f9g8_19
|
|
h8: int64 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 +
|
|
f7g1_2 + f8g0 + f9g9_38
|
|
h9: int64 = f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 +
|
|
f8g1 + f9g0
|
|
|
|
c0 = ashr((h0 + (1'i64 shl 25)), 26); h1 = h1 + c0; h0 -= (c0 shl 26)
|
|
c4 = ashr((h4 + (1'i64 shl 25)), 26); h5 = h5 + c4; h4 -= (c4 shl 26)
|
|
c1 = ashr((h1 + (1'i64 shl 24)), 25); h2 = h2 + c1; h1 -= (c1 shl 25)
|
|
c5 = ashr((h5 + (1'i64 shl 24)), 25); h6 = h6 + c5; h5 -= (c5 shl 25)
|
|
c2 = ashr((h2 + (1'i64 shl 25)), 26); h3 = h3 + c2; h2 -= (c2 shl 26)
|
|
c6 = ashr((h6 + (1'i64 shl 25)), 26); h7 = h7 + c6; h6 -= (c6 shl 26)
|
|
c3 = ashr((h3 + (1'i64 shl 24)), 25); h4 = h4 + c3; h3 -= (c3 shl 25)
|
|
c7 = ashr((h7 + (1'i64 shl 24)), 25); h8 = h8 + c7; h7 -= (c7 shl 25)
|
|
c4 = ashr((h4 + (1'i64 shl 25)), 26); h5 = h5 + c4; h4 -= (c4 shl 26)
|
|
c8 = ashr((h8 + (1'i64 shl 25)), 26); h9 = h9 + c8; h8 -= (c8 shl 26)
|
|
c9 = ashr((h9 + (1'i64 shl 24)), 25); h0 = h0 + (c9 * 19); h9 -= (c9 shl 25)
|
|
c0 = ashr((h0 + (1'i64 shl 25)), 26); h1 = h1 + c0; h0 -= (c0 shl 26)
|
|
|
|
h[0] = cast[int32](h0)
|
|
h[1] = cast[int32](h1)
|
|
h[2] = cast[int32](h2)
|
|
h[3] = cast[int32](h3)
|
|
h[4] = cast[int32](h4)
|
|
h[5] = cast[int32](h5)
|
|
h[6] = cast[int32](h6)
|
|
h[7] = cast[int32](h7)
|
|
h[8] = cast[int32](h8)
|
|
h[9] = cast[int32](h9)
|
|
|
|
proc feNeg(h: var Fe, f: Fe) =
|
|
var f0 = f[0]; var f1 = f[1]; var f2 = f[2]; var f3 = f[3]; var f4 = f[4]
|
|
var f5 = f[5]; var f6 = f[6]; var f7 = f[7]; var f8 = f[8]; var f9 = f[9]
|
|
var h0 = -f0; var h1 = -f1; var h2 = -f2; var h3 = -f3; var h4 = -f4
|
|
var h5 = -f5; var h6 = -f6; var h7 = -f7; var h8 = -f8; var h9 = -f9
|
|
h[0] = h0; h[1] = h1; h[2] = h2; h[3] = h3; h[4] = h4
|
|
h[5] = h5; h[6] = h6; h[7] = h7; h[8] = h8; h[9] = h9
|
|
|
|
proc verify32(x: openArray[byte], y: openArray[byte]): int32 =
|
|
var d = 0'u32
|
|
d = d or (x[0] xor y[0])
|
|
d = d or (x[1] xor y[1])
|
|
d = d or (x[2] xor y[2])
|
|
d = d or (x[3] xor y[3])
|
|
d = d or (x[4] xor y[4])
|
|
d = d or (x[5] xor y[5])
|
|
d = d or (x[6] xor y[6])
|
|
d = d or (x[7] xor y[7])
|
|
d = d or (x[8] xor y[8])
|
|
d = d or (x[9] xor y[9])
|
|
d = d or (x[10] xor y[10])
|
|
d = d or (x[11] xor y[11])
|
|
d = d or (x[12] xor y[12])
|
|
d = d or (x[13] xor y[13])
|
|
d = d or (x[14] xor y[14])
|
|
d = d or (x[15] xor y[15])
|
|
d = d or (x[16] xor y[16])
|
|
d = d or (x[17] xor y[17])
|
|
d = d or (x[18] xor y[18])
|
|
d = d or (x[19] xor y[19])
|
|
d = d or (x[20] xor y[20])
|
|
d = d or (x[21] xor y[21])
|
|
d = d or (x[22] xor y[22])
|
|
d = d or (x[23] xor y[23])
|
|
d = d or (x[24] xor y[24])
|
|
d = d or (x[25] xor y[25])
|
|
d = d or (x[26] xor y[26])
|
|
d = d or (x[27] xor y[27])
|
|
d = d or (x[28] xor y[28])
|
|
d = d or (x[29] xor y[29])
|
|
d = d or (x[30] xor y[30])
|
|
d = d or (x[31] xor y[31])
|
|
result = cast[int32]((1'u32 and ((d - 1) shr 8)) - 1)
|
|
|
|
proc feIsNegative(f: Fe): int32 =
|
|
var s: array[32, byte]
|
|
feToBytes(s, f)
|
|
result = cast[int32](s[0] and 1'u8)
|
|
|
|
proc feIsNonZero(f: Fe): int32 =
|
|
var s: array[32, byte]
|
|
feToBytes(s, f)
|
|
result = verify32(s, ZeroFe)
|
|
|
|
proc feSq(h: var Fe, f: Fe) =
|
|
var f0 = f[0]; var f1 = f[1]; var f2 = f[2]; var f3 = f[3]; var f4 = f[4];
|
|
var f5 = f[5]; var f6 = f[6]; var f7 = f[7]; var f8 = f[8]; var f9 = f[9];
|
|
var f0_2: int32 = 2 * f0
|
|
var f1_2: int32 = 2 * f1
|
|
var f2_2: int32 = 2 * f2
|
|
var f3_2: int32 = 2 * f3
|
|
var f4_2: int32 = 2 * f4
|
|
var f5_2: int32 = 2 * f5
|
|
var f6_2: int32 = 2 * f6
|
|
var f7_2: int32 = 2 * f7
|
|
var f5_38: int32 = 38 * f5
|
|
var f6_19: int32 = 19 * f6
|
|
var f7_38: int32 = 38 * f7
|
|
var f8_19: int32 = 19 * f8
|
|
var f9_38: int32 = 38 * f9
|
|
var f0f0: int64 = f0 * cast[int64](f0)
|
|
var f0f1_2: int64 = f0_2 * cast[int64](f1)
|
|
var f0f2_2: int64 = f0_2 * cast[int64](f2)
|
|
var f0f3_2: int64 = f0_2 * cast[int64](f3)
|
|
var f0f4_2: int64 = f0_2 * cast[int64](f4)
|
|
var f0f5_2: int64 = f0_2 * cast[int64](f5)
|
|
var f0f6_2: int64 = f0_2 * cast[int64](f6)
|
|
var f0f7_2: int64 = f0_2 * cast[int64](f7)
|
|
var f0f8_2: int64 = f0_2 * cast[int64](f8)
|
|
var f0f9_2: int64 = f0_2 * cast[int64](f9)
|
|
var f1f1_2: int64 = f1_2 * cast[int64](f1)
|
|
var f1f2_2: int64 = f1_2 * cast[int64](f2)
|
|
var f1f3_4: int64 = f1_2 * cast[int64](f3_2)
|
|
var f1f4_2: int64 = f1_2 * cast[int64](f4)
|
|
var f1f5_4: int64 = f1_2 * cast[int64](f5_2)
|
|
var f1f6_2: int64 = f1_2 * cast[int64](f6)
|
|
var f1f7_4: int64 = f1_2 * cast[int64](f7_2)
|
|
var f1f8_2: int64 = f1_2 * cast[int64](f8)
|
|
var f1f9_76: int64 = f1_2 * cast[int64](f9_38)
|
|
var f2f2: int64 = f2 * cast[int64](f2)
|
|
var f2f3_2: int64 = f2_2 * cast[int64](f3)
|
|
var f2f4_2: int64 = f2_2 * cast[int64](f4)
|
|
var f2f5_2: int64 = f2_2 * cast[int64](f5)
|
|
var f2f6_2: int64 = f2_2 * cast[int64](f6)
|
|
var f2f7_2: int64 = f2_2 * cast[int64](f7)
|
|
var f2f8_38: int64 = f2_2 * cast[int64](f8_19)
|
|
var f2f9_38: int64 = f2 * cast[int64](f9_38)
|
|
var f3f3_2: int64 = f3_2 * cast[int64](f3)
|
|
var f3f4_2: int64 = f3_2 * cast[int64](f4)
|
|
var f3f5_4: int64 = f3_2 * cast[int64](f5_2)
|
|
var f3f6_2: int64 = f3_2 * cast[int64](f6)
|
|
var f3f7_76: int64 = f3_2 * cast[int64](f7_38)
|
|
var f3f8_38: int64 = f3_2 * cast[int64](f8_19)
|
|
var f3f9_76: int64 = f3_2 * cast[int64](f9_38)
|
|
var f4f4: int64 = f4 * cast[int64](f4)
|
|
var f4f5_2: int64 = f4_2 * cast[int64](f5)
|
|
var f4f6_38: int64 = f4_2 * cast[int64](f6_19)
|
|
var f4f7_38: int64 = f4 * cast[int64](f7_38)
|
|
var f4f8_38: int64 = f4_2 * cast[int64](f8_19)
|
|
var f4f9_38: int64 = f4 * cast[int64](f9_38)
|
|
var f5f5_38: int64 = f5 * cast[int64](f5_38)
|
|
var f5f6_38: int64 = f5_2 * cast[int64](f6_19)
|
|
var f5f7_76: int64 = f5_2 * cast[int64](f7_38)
|
|
var f5f8_38: int64 = f5_2 * cast[int64](f8_19)
|
|
var f5f9_76: int64 = f5_2 * cast[int64](f9_38)
|
|
var f6f6_19: int64 = f6 * cast[int64](f6_19)
|
|
var f6f7_38: int64 = f6 * cast[int64](f7_38)
|
|
var f6f8_38: int64 = f6_2 * cast[int64](f8_19)
|
|
var f6f9_38: int64 = f6 * cast[int64](f9_38)
|
|
var f7f7_38: int64 = f7 * cast[int64](f7_38)
|
|
var f7f8_38: int64 = f7_2 * cast[int64](f8_19)
|
|
var f7f9_76: int64 = f7_2 * cast[int64](f9_38)
|
|
var f8f8_19: int64 = f8 * cast[int64](f8_19)
|
|
var f8f9_38: int64 = f8 * cast[int64](f9_38)
|
|
var f9f9_38: int64 = f9 * cast[int64](f9_38)
|
|
var h0: int64 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38
|
|
var h1: int64 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38
|
|
var h2: int64 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19
|
|
var h3: int64 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38
|
|
var h4: int64 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38
|
|
var h5: int64 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38
|
|
var h6: int64 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19
|
|
var h7: int64 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38
|
|
var h8: int64 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38
|
|
var h9: int64 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2
|
|
var c0, c1, c2, c3, c4, c5, c6, c7, c8, c9: int64
|
|
|
|
c0 = ashr((h0 + (1'i64 shl 25)), 26); h1 += c0; h0 -= c0 shl 26
|
|
c4 = ashr((h4 + (1'i64 shl 25)), 26); h5 += c4; h4 -= c4 shl 26
|
|
c1 = ashr((h1 + (1'i64 shl 24)), 25); h2 += c1; h1 -= c1 shl 25
|
|
c5 = ashr((h5 + (1'i64 shl 24)), 25); h6 += c5; h5 -= c5 shl 25
|
|
c2 = ashr((h2 + (1'i64 shl 25)), 26); h3 += c2; h2 -= c2 shl 26
|
|
c6 = ashr((h6 + (1'i64 shl 25)), 26); h7 += c6; h6 -= c6 shl 26
|
|
c3 = ashr((h3 + (1'i64 shl 24)), 25); h4 += c3; h3 -= c3 shl 25
|
|
c7 = ashr((h7 + (1'i64 shl 24)), 25); h8 += c7; h7 -= c7 shl 25
|
|
c4 = ashr((h4 + (1'i64 shl 25)), 26); h5 += c4; h4 -= c4 shl 26
|
|
c8 = ashr((h8 + (1'i64 shl 25)), 26); h9 += c8; h8 -= c8 shl 26
|
|
c9 = ashr((h9 + (1'i64 shl 24)), 25); h0 += c9 * 19; h9 -= c9 shl 25
|
|
c0 = ashr((h0 + (1'i64 shl 25)), 26); h1 += c0; h0 -= c0 shl 26
|
|
|
|
h[0] = cast[int32](h0)
|
|
h[1] = cast[int32](h1)
|
|
h[2] = cast[int32](h2)
|
|
h[3] = cast[int32](h3)
|
|
h[4] = cast[int32](h4)
|
|
h[5] = cast[int32](h5)
|
|
h[6] = cast[int32](h6)
|
|
h[7] = cast[int32](h7)
|
|
h[8] = cast[int32](h8)
|
|
h[9] = cast[int32](h9)
|
|
|
|
proc feSq2(h: var Fe, f: Fe) =
|
|
var f0 = f[0]; var f1 = f[1]; var f2 = f[2]; var f3 = f[3]; var f4 = f[4]
|
|
var f5 = f[5]; var f6 = f[6]; var f7 = f[7]; var f8 = f[8]; var f9 = f[9]
|
|
var f0_2 = 2 * f0
|
|
var f1_2 = 2 * f1
|
|
var f2_2 = 2 * f2
|
|
var f3_2 = 2 * f3
|
|
var f4_2 = 2 * f4
|
|
var f5_2 = 2 * f5
|
|
var f6_2 = 2 * f6
|
|
var f7_2 = 2 * f7
|
|
var f5_38 = 38 * f5
|
|
var f6_19 = 19 * f6
|
|
var f7_38 = 38 * f7
|
|
var f8_19 = 19 * f8
|
|
var f9_38 = 38 * f9
|
|
var f0f0 = cast[int64](f0) * cast[int64](f0)
|
|
var f0f1_2 = cast[int64](f0_2) * cast[int64](f1)
|
|
var f0f2_2 = cast[int64](f0_2) * cast[int64](f2)
|
|
var f0f3_2 = cast[int64](f0_2) * cast[int64](f3)
|
|
var f0f4_2 = cast[int64](f0_2) * cast[int64](f4)
|
|
var f0f5_2 = cast[int64](f0_2) * cast[int64](f5)
|
|
var f0f6_2 = cast[int64](f0_2) * cast[int64](f6)
|
|
var f0f7_2 = cast[int64](f0_2) * cast[int64](f7)
|
|
var f0f8_2 = cast[int64](f0_2) * cast[int64](f8)
|
|
var f0f9_2 = cast[int64](f0_2) * cast[int64](f9)
|
|
var f1f1_2 = cast[int64](f1_2) * cast[int64](f1)
|
|
var f1f2_2 = cast[int64](f1_2) * cast[int64](f2)
|
|
var f1f3_4 = cast[int64](f1_2) * cast[int64](f3_2)
|
|
var f1f4_2 = cast[int64](f1_2) * cast[int64](f4)
|
|
var f1f5_4 = cast[int64](f1_2) * cast[int64](f5_2)
|
|
var f1f6_2 = cast[int64](f1_2) * cast[int64](f6)
|
|
var f1f7_4 = cast[int64](f1_2) * cast[int64](f7_2)
|
|
var f1f8_2 = cast[int64](f1_2) * cast[int64](f8)
|
|
var f1f9_76 = cast[int64](f1_2) * cast[int64](f9_38)
|
|
var f2f2 = cast[int64](f2) * cast[int64](f2)
|
|
var f2f3_2 = cast[int64](f2_2) * cast[int64](f3)
|
|
var f2f4_2 = cast[int64](f2_2) * cast[int64](f4)
|
|
var f2f5_2 = cast[int64](f2_2) * cast[int64](f5)
|
|
var f2f6_2 = cast[int64](f2_2) * cast[int64](f6)
|
|
var f2f7_2 = cast[int64](f2_2) * cast[int64](f7)
|
|
var f2f8_38 = cast[int64](f2_2) * cast[int64](f8_19)
|
|
var f2f9_38 = cast[int64](f2) * cast[int64](f9_38)
|
|
var f3f3_2 = cast[int64](f3_2) * cast[int64](f3)
|
|
var f3f4_2 = cast[int64](f3_2) * cast[int64](f4)
|
|
var f3f5_4 = cast[int64](f3_2) * cast[int64](f5_2)
|
|
var f3f6_2 = cast[int64](f3_2) * cast[int64](f6)
|
|
var f3f7_76 = cast[int64](f3_2) * cast[int64](f7_38)
|
|
var f3f8_38 = cast[int64](f3_2) * cast[int64](f8_19)
|
|
var f3f9_76 = cast[int64](f3_2) * cast[int64](f9_38)
|
|
var f4f4 = cast[int64](f4) * cast[int64](f4)
|
|
var f4f5_2 = cast[int64](f4_2) * cast[int64](f5)
|
|
var f4f6_38 = cast[int64](f4_2) * cast[int64](f6_19)
|
|
var f4f7_38 = cast[int64](f4) * cast[int64](f7_38)
|
|
var f4f8_38 = cast[int64](f4_2) * cast[int64](f8_19)
|
|
var f4f9_38 = cast[int64](f4) * cast[int64](f9_38)
|
|
var f5f5_38 = cast[int64](f5) * cast[int64](f5_38)
|
|
var f5f6_38 = cast[int64](f5_2) * cast[int64](f6_19)
|
|
var f5f7_76 = cast[int64](f5_2) * cast[int64](f7_38)
|
|
var f5f8_38 = cast[int64](f5_2) * cast[int64](f8_19)
|
|
var f5f9_76 = cast[int64](f5_2) * cast[int64](f9_38)
|
|
var f6f6_19 = cast[int64](f6) * cast[int64](f6_19)
|
|
var f6f7_38 = cast[int64](f6) * cast[int64](f7_38)
|
|
var f6f8_38 = cast[int64](f6_2) * cast[int64](f8_19)
|
|
var f6f9_38 = cast[int64](f6) * cast[int64](f9_38)
|
|
var f7f7_38 = cast[int64](f7) * cast[int64](f7_38)
|
|
var f7f8_38 = cast[int64](f7_2) * cast[int64](f8_19)
|
|
var f7f9_76 = cast[int64](f7_2) * cast[int64](f9_38)
|
|
var f8f8_19 = cast[int64](f8) * cast[int64](f8_19)
|
|
var f8f9_38 = cast[int64](f8) * cast[int64](f9_38)
|
|
var f9f9_38 = cast[int64](f9) * cast[int64](f9_38)
|
|
var
|
|
c0, c1, c2, c3, c4, c5, c6, c7, c8, c9: int64
|
|
h0: int64 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38
|
|
h1: int64 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38
|
|
h2: int64 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19
|
|
h3: int64 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38
|
|
h4: int64 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38
|
|
h5: int64 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38
|
|
h6: int64 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19
|
|
h7: int64 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38
|
|
h8: int64 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38
|
|
h9: int64 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2
|
|
|
|
h0 += h0; h1 += h1; h2 += h2; h3 += h3; h4 += h4;
|
|
h5 += h5; h6 += h6; h7 += h7; h8 += h8; h9 += h9;
|
|
|
|
c0 = ashr((h0 + (1'i64 shl 25)), 26); h1 += c0; h0 -= c0 shl 26
|
|
c4 = ashr((h4 + (1'i64 shl 25)), 26); h5 += c4; h4 -= c4 shl 26
|
|
c1 = ashr((h1 + (1'i64 shl 24)), 25); h2 += c1; h1 -= c1 shl 25
|
|
c5 = ashr((h5 + (1'i64 shl 24)), 25); h6 += c5; h5 -= c5 shl 25
|
|
c2 = ashr((h2 + (1'i64 shl 25)), 26); h3 += c2; h2 -= c2 shl 26
|
|
c6 = ashr((h6 + (1'i64 shl 25)), 26); h7 += c6; h6 -= c6 shl 26
|
|
c3 = ashr((h3 + (1'i64 shl 24)), 25); h4 += c3; h3 -= c3 shl 25
|
|
c7 = ashr((h7 + (1'i64 shl 24)), 25); h8 += c7; h7 -= c7 shl 25
|
|
c4 = ashr((h4 + (1'i64 shl 25)), 26); h5 += c4; h4 -= c4 shl 26
|
|
c8 = ashr((h8 + (1'i64 shl 25)), 26); h9 += c8; h8 -= c8 shl 26
|
|
c9 = ashr((h9 + (1'i64 shl 24)), 25); h0 += c9 * 19; h9 -= c9 shl 25
|
|
c0 = ashr((h0 + (1'i64 shl 25)), 26); h1 += c0; h0 -= c0 shl 26
|
|
|
|
h[0] = cast[int32](h0)
|
|
h[1] = cast[int32](h1)
|
|
h[2] = cast[int32](h2)
|
|
h[3] = cast[int32](h3)
|
|
h[4] = cast[int32](h4)
|
|
h[5] = cast[int32](h5)
|
|
h[6] = cast[int32](h6)
|
|
h[7] = cast[int32](h7)
|
|
h[8] = cast[int32](h8)
|
|
h[9] = cast[int32](h9)
|
|
|
|
proc feInvert(outfe: var Fe, z: Fe) =
|
|
var t0, t1, t2, t3: Fe
|
|
feSq(t0, z)
|
|
for i in 1..<1: feSq(t0, t0)
|
|
feSq(t1, t0)
|
|
for i in 1..<2: feSq(t1, t1)
|
|
feMul(t1, z, t1)
|
|
feMul(t0, t0, t1)
|
|
feSq(t2, t0)
|
|
for i in 1..<1: feSq(t2, t2)
|
|
feMul(t1, t1, t2)
|
|
feSq(t2, t1)
|
|
for i in 1..<5: feSq(t2, t2)
|
|
feMul(t1, t2, t1)
|
|
feSq(t2, t1)
|
|
for i in 1..<10: feSq(t2, t2)
|
|
feMul(t2, t2, t1)
|
|
feSq(t3, t2)
|
|
for i in 1..<20: feSq(t3, t3)
|
|
feMul(t2, t3, t2)
|
|
feSq(t2, t2)
|
|
for i in 1..<10: feSq(t2, t2)
|
|
feMul(t1, t2, t1)
|
|
feSq(t2, t1)
|
|
for i in 1..<50: feSq(t2, t2)
|
|
feMul(t2, t2, t1)
|
|
feSq(t3, t2)
|
|
for i in 1..<100: feSq(t3, t3)
|
|
feMul(t2, t3, t2)
|
|
feSq(t2, t2)
|
|
for i in 1..<50: feSq(t2, t2)
|
|
feMul(t1, t2, t1)
|
|
feSq(t1, t1)
|
|
for i in 1..<5: feSq(t1, t1)
|
|
feMul(outfe, t1, t0)
|
|
|
|
proc fePow22523(outfe: var Fe, z: Fe) =
|
|
var t0, t1, t2: Fe
|
|
feSq(t0, z)
|
|
for i in 1..<1: feSq(t0, t0)
|
|
feSq(t1, t0)
|
|
for i in 1..<2: feSq(t1, t1)
|
|
feMul(t1, z, t1)
|
|
feMul(t0, t0, t1)
|
|
feSq(t0, t0)
|
|
for i in 1..<1: feSq(t0, t0)
|
|
feMul(t0, t1, t0)
|
|
feSq(t1, t0)
|
|
for i in 1..<5: feSq(t1, t1)
|
|
feMul(t0, t1, t0)
|
|
feSq(t1, t0)
|
|
for i in 1..<10: feSq(t1, t1)
|
|
feMul(t1, t1, t0)
|
|
feSq(t2, t1)
|
|
for i in 1..<20: feSq(t2, t2)
|
|
feMul(t1, t2, t1)
|
|
feSq(t1, t1)
|
|
for i in 1..<10: feSq(t1, t1)
|
|
feMul(t0, t1, t0)
|
|
feSq(t1, t0)
|
|
for i in 1..<50: feSq(t1, t1)
|
|
feMul(t1, t1, t0)
|
|
feSq(t2, t1)
|
|
for i in 1..<100: feSq(t2, t2)
|
|
feMul(t1, t2, t1)
|
|
feSq(t1, t1)
|
|
for i in 1..<50: feSq(t1, t1)
|
|
feMul(t0, t1, t0)
|
|
feSq(t0, t0)
|
|
for i in 1..<2: feSq(t0, t0)
|
|
feMul(outfe, t0, z)
|
|
|
|
proc geAdd(r: var GeP1P1, p: GeP3, q: GeCached) =
|
|
var t0: Fe
|
|
feAdd(r.x, p.y, p.x)
|
|
feSub(r.y, p.y, p.x)
|
|
feMul(r.z, r.x, q.yplusx)
|
|
feMul(r.y, r.y, q.yminusx)
|
|
feMul(r.t, q.t2d, p.t)
|
|
feMul(r.x, p.z, q.z)
|
|
feAdd(t0,r.x, r.x)
|
|
feSub(r.x, r.z, r.y)
|
|
feAdd(r.y, r.z, r.y)
|
|
feAdd(r.z, t0, r.t)
|
|
feSub(r.t, t0, r.t)
|
|
|
|
proc geFromBytesNegateVartime(h: var GeP3, s: openArray[byte]): int32 =
|
|
var u, v, v3, vxx, check: Fe
|
|
|
|
feFromBytes(h.y, s)
|
|
fe1(h.z)
|
|
feSq(u, h.y)
|
|
|
|
feMul(v, u, DConst)
|
|
feSub(u, u, h.z)
|
|
feAdd(v, v, h.z)
|
|
|
|
feSq(v3, v)
|
|
feMul(v3, v3, v)
|
|
feSq(h.x, v3)
|
|
feMul(h.x, h.x, v)
|
|
feMul(h.x, h.x, u)
|
|
|
|
fePow22523(h.x, h.x)
|
|
feMul(h.x, h.x, v3)
|
|
feMul(h.x, h.x, u)
|
|
|
|
feSq(vxx, h.x)
|
|
feMul(vxx, vxx, v)
|
|
feSub(check, vxx, u)
|
|
if feIsNonZero(check) != 0:
|
|
feAdd(check, vxx, u)
|
|
if feIsNonZero(check) != 0:
|
|
return -1;
|
|
feMul(h.x, h.x, SqrTm1)
|
|
|
|
if feIsNegative(h.x) == cast[int32](s[31] shr 7):
|
|
feNeg(h.x, h.x)
|
|
|
|
feMul(h.t, h.x, h.y)
|
|
return 0
|
|
|
|
proc geMadd(r: var GeP1P1, p: GeP3, q: GePrecomp) =
|
|
var t0: Fe
|
|
feAdd(r.x, p.y, p.x)
|
|
feSub(r.y, p.y, p.x)
|
|
feMul(r.z, r.x, q.yplusx)
|
|
feMul(r.y, r.y, q.yminusx)
|
|
feMul(r.t, q.xy2d, p.t)
|
|
feAdd(t0, p.z, p.z)
|
|
feSub(r.x, r.z, r.y)
|
|
feAdd(r.y, r.z, r.y)
|
|
feAdd(r.z, t0, r.t)
|
|
feSub(r.t, t0, r.t)
|
|
|
|
proc geMsub(r: var GeP1P1, p: GeP3, q: GePrecomp) =
|
|
var t0: Fe
|
|
feAdd(r.x, p.y, p.x)
|
|
feSub(r.y, p.y, p.x)
|
|
feMul(r.z, r.x, q.yminusx)
|
|
feMul(r.y, r.y, q.yplusx)
|
|
feMul(r.t, q.xy2d, p.t)
|
|
feAdd(t0, p.z, p.z)
|
|
feSub(r.x, r.z, r.y)
|
|
feAdd(r.y, r.z, r.y)
|
|
feSub(r.z, t0, r.t)
|
|
feAdd(r.t, t0, r.t)
|
|
|
|
proc geSub(r: var GeP1P1, p: GeP3, q: GeCached) =
|
|
var t0: Fe
|
|
feAdd(r.x, p.y, p.x)
|
|
feSub(r.y, p.y, p.x)
|
|
feMul(r.z, r.x, q.yminusx)
|
|
feMul(r.y, r.y, q.yplusx)
|
|
feMul(r.t, q.t2d, p.t)
|
|
feMul(r.x, p.z, q.z)
|
|
feAdd(t0, r.x, r.x)
|
|
feSub(r.x, r.z, r.y)
|
|
feAdd(r.y, r.z, r.y)
|
|
feSub(r.z, t0, r.t)
|
|
feAdd(r.t, t0, r.t)
|
|
|
|
proc geToBytes(s: var openArray[byte], h: GeP2) =
|
|
var recip, x, y: Fe
|
|
feInvert(recip, h.z)
|
|
feMul(x, h.x, recip)
|
|
feMul(y, h.y, recip)
|
|
feToBytes(s, y)
|
|
s[31] = s[31] xor cast[byte](feIsNegative(x) shl 7)
|
|
|
|
proc geP1P1toP2(r: var GeP2, p: GeP1P1) =
|
|
feMul(r.x, p.x, p.t)
|
|
feMul(r.y, p.y, p.z)
|
|
feMul(r.z, p.z, p.t)
|
|
|
|
proc geP1P1toP3(r: var GeP3, p: GeP1P1) =
|
|
feMul(r.x, p.x, p.t)
|
|
feMul(r.y, p.y, p.z)
|
|
feMul(r.z, p.z, p.t)
|
|
feMul(r.t, p.x, p.y)
|
|
|
|
proc geP20(h: var GeP2) =
|
|
fe0(h.x)
|
|
fe1(h.y)
|
|
fe1(h.z)
|
|
|
|
proc geP2dbl(r: var GeP1P1, p: GeP2) =
|
|
var t0: Fe
|
|
feSq(r.x, p.x)
|
|
feSq(r.z, p.y)
|
|
feSq2(r.t, p.z)
|
|
feAdd(r.y, p.x, p.y)
|
|
feSq(t0, r.y)
|
|
feAdd(r.y, r.z, r.x)
|
|
feSub(r.z, r.z, r.x)
|
|
feSub(r.x, t0, r.y)
|
|
feSub(r.t, r.t, r.z)
|
|
|
|
proc geP30(h: var GeP3) =
|
|
fe0(h.x)
|
|
fe1(h.y)
|
|
fe1(h.z)
|
|
fe0(h.t)
|
|
|
|
proc geP3toP2(r: var GeP2, p: GeP3) =
|
|
feCopy(r.x, p.x)
|
|
feCopy(r.y, p.y)
|
|
feCopy(r.z, p.z)
|
|
|
|
proc geP3dbl(r: var GeP1P1, p: GeP3) =
|
|
var q: GeP2
|
|
geP3toP2(q, p)
|
|
geP2dbl(r, q)
|
|
|
|
proc geP3ToBytes(s: var openArray[byte], h: GeP3) =
|
|
var recip, x, y: Fe
|
|
|
|
feInvert(recip, h.z);
|
|
feMul(x, h.x, recip);
|
|
feMul(y, h.y, recip);
|
|
feToBytes(s, y);
|
|
s[31] = s[31] xor cast[byte](feIsNegative(x) shl 7)
|
|
|
|
proc geP3ToCached(r: var GeCached, p: GeP3) =
|
|
feAdd(r.yplusx, p.y, p.x)
|
|
feSub(r.yminusx, p.y, p.x)
|
|
feCopy(r.z, p.z)
|
|
feMul(r.t2d, p.t, D2Const)
|
|
|
|
proc gePrecomp0(h: var GePrecomp) =
|
|
fe1(h.yplusx)
|
|
fe1(h.yminusx)
|
|
fe0(h.xy2d)
|
|
|
|
proc equal(b, c: int8): byte =
|
|
var ub = cast[byte](b)
|
|
var uc = cast[byte](c)
|
|
var x = ub xor uc
|
|
var y = cast[uint32](x)
|
|
y = y - 1
|
|
y = y shr 31
|
|
result = cast[byte](y)
|
|
|
|
proc negative(b: int8): byte =
|
|
var x = cast[uint64](b)
|
|
x = x shr 63
|
|
result = cast[byte](x)
|
|
|
|
proc cmov(t: var GePrecomp, u: GePrecomp, b: byte) =
|
|
feCmov(t.yplusx, u.yplusx, b)
|
|
feCmov(t.yminusx, u.yminusx, b)
|
|
feCmov(t.xy2d, u.xy2d, b)
|
|
|
|
proc select(t: var GePrecomp, pos: int, b: int8) =
|
|
var minust: GePrecomp
|
|
var bnegative = negative(b)
|
|
var babs = cast[uint8](b) - (((-bnegative) and cast[uint8](b)) shl 1)
|
|
gePrecomp0(t)
|
|
cmov(t, BasePrecomp[pos][0], equal(cast[int8](babs), 1'i8))
|
|
cmov(t, BasePrecomp[pos][1], equal(cast[int8](babs), 2'i8))
|
|
cmov(t, BasePrecomp[pos][2], equal(cast[int8](babs), 3'i8))
|
|
cmov(t, BasePrecomp[pos][3], equal(cast[int8](babs), 4'i8))
|
|
cmov(t, BasePrecomp[pos][4], equal(cast[int8](babs), 5'i8))
|
|
cmov(t, BasePrecomp[pos][5], equal(cast[int8](babs), 6'i8))
|
|
cmov(t, BasePrecomp[pos][6], equal(cast[int8](babs), 7'i8))
|
|
cmov(t, BasePrecomp[pos][7], equal(cast[int8](babs), 8'i8))
|
|
feCopy(minust.yplusx, t.yminusx)
|
|
feCopy(minust.yminusx, t.yplusx)
|
|
feNeg(minust.xy2d, t.xy2d)
|
|
cmov(t, minust, bnegative)
|
|
|
|
proc geScalarMultBase(h: var GeP3, a: openArray[byte]) =
|
|
var e: array[64, int8]
|
|
var carry: int8
|
|
var r: GeP1P1
|
|
var s: GeP2
|
|
var t: GePrecomp
|
|
|
|
for i in 0..<32:
|
|
e[2 * i + 0] = cast[int8]((a[i] shr 0) and 15)
|
|
e[2 * i + 1] = cast[int8]((a[i] shr 4) and 15)
|
|
|
|
carry = 0
|
|
for i in 0..<63:
|
|
e[i] += carry
|
|
carry = e[i] + 8
|
|
carry = carry shr 4
|
|
e[i] -= carry shl 4
|
|
|
|
e[63] += carry
|
|
geP30(h)
|
|
for i in countup(1, 63, 2):
|
|
select(t, i div 2, e[i])
|
|
geMadd(r, h, t)
|
|
geP1P1toP3(h, r)
|
|
|
|
geP3dbl(r, h); geP1P1toP2(s, r)
|
|
geP2dbl(r, s); geP1P1toP2(s, r)
|
|
geP2dbl(r, s); geP1P1toP2(s, r)
|
|
geP2dbl(r, s); geP1P1toP3(h, r)
|
|
|
|
for i in countup(0, 63, 2):
|
|
select(t, i div 2, e[i])
|
|
geMadd(r, h, t)
|
|
geP1P1toP3(h, r)
|
|
|
|
proc scMulAdd(s: var openArray[byte], a, b, c: openArray[byte]) =
|
|
var a0 = 2097151'i64 and cast[int64](load_3(a.toOpenArray(0, 2)))
|
|
var a1 = 2097151'i64 and cast[int64](load_4(a.toOpenArray(2, 5)) shr 5)
|
|
var a2 = 2097151'i64 and cast[int64](load_3(a.toOpenArray(5, 7)) shr 2)
|
|
var a3 = 2097151'i64 and cast[int64](load_4(a.toOpenArray(7, 10)) shr 7)
|
|
var a4 = 2097151'i64 and cast[int64](load_4(a.toOpenArray(10, 13)) shr 4)
|
|
var a5 = 2097151'i64 and cast[int64](load_3(a.toOpenArray(13, 15)) shr 1)
|
|
var a6 = 2097151'i64 and cast[int64](load_4(a.toOpenArray(15, 18)) shr 6)
|
|
var a7 = 2097151'i64 and cast[int64](load_3(a.toOpenArray(18, 20)) shr 3)
|
|
var a8 = 2097151'i64 and cast[int64](load_3(a.toOpenArray(21, 23)))
|
|
var a9 = 2097151'i64 and cast[int64](load_4(a.toOpenArray(23, 26)) shr 5)
|
|
var a10 = 2097151'i64 and cast[int64](load_3(a.toOpenArray(26, 28)) shr 2)
|
|
var a11 = cast[int64](load_4(a.toOpenArray(28, 31)) shr 7)
|
|
var b0 = 2097151'i64 and cast[int64](load_3(b.toOpenArray(0, 2)))
|
|
var b1 = 2097151'i64 and cast[int64](load_4(b.toOpenArray(2, 5)) shr 5)
|
|
var b2 = 2097151'i64 and cast[int64](load_3(b.toOpenArray(5, 7)) shr 2)
|
|
var b3 = 2097151'i64 and cast[int64](load_4(b.toOpenArray(7, 10)) shr 7)
|
|
var b4 = 2097151'i64 and cast[int64](load_4(b.toOpenArray(10, 13)) shr 4)
|
|
var b5 = 2097151'i64 and cast[int64](load_3(b.toOpenArray(13, 15)) shr 1)
|
|
var b6 = 2097151'i64 and cast[int64](load_4(b.toOpenArray(15, 18)) shr 6)
|
|
var b7 = 2097151'i64 and cast[int64](load_3(b.toOpenArray(18, 20)) shr 3)
|
|
var b8 = 2097151'i64 and cast[int64](load_3(b.toOpenArray(21, 23)))
|
|
var b9 = 2097151'i64 and cast[int64](load_4(b.toOpenArray(23, 26)) shr 5)
|
|
var b10 = 2097151'i64 and cast[int64](load_3(b.toOpenArray(26, 28)) shr 2)
|
|
var b11 = cast[int64](load_4(b.toOpenArray(28, 31)) shr 7)
|
|
var c0 = 2097151'i64 and cast[int64](load_3(c.toOpenArray(0, 2)))
|
|
var c1 = 2097151'i64 and cast[int64](load_4(c.toOpenArray(2, 5)) shr 5)
|
|
var c2 = 2097151'i64 and cast[int64](load_3(c.toOpenArray(5, 7)) shr 2)
|
|
var c3 = 2097151'i64 and cast[int64](load_4(c.toOpenArray(7, 10)) shr 7)
|
|
var c4 = 2097151'i64 and cast[int64](load_4(c.toOpenArray(10, 13)) shr 4)
|
|
var c5 = 2097151'i64 and cast[int64](load_3(c.toOpenArray(13, 15)) shr 1)
|
|
var c6 = 2097151'i64 and cast[int64](load_4(c.toOpenArray(15, 18)) shr 6)
|
|
var c7 = 2097151'i64 and cast[int64](load_3(c.toOpenArray(18, 20)) shr 3)
|
|
var c8 = 2097151'i64 and cast[int64](load_3(c.toOpenArray(21, 23)))
|
|
var c9 = 2097151'i64 and cast[int64](load_4(c.toOpenArray(23, 26)) shr 5)
|
|
var c10 = 2097151'i64 and cast[int64](load_3(c.toOpenArray(26, 28)) shr 2)
|
|
var c11 = cast[int64](load_4(c.toOpenArray(28, 31)) shr 7)
|
|
var
|
|
s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12: int64
|
|
s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23: int64
|
|
cr0, cr1, cr2, cr3, cr4, cr5, cr6, cr7, cr8, cr9, cr10, cr11: int64
|
|
cr12, cr13, cr14, cr15, cr16, cr17, cr18, cr19, cr20, cr21, cr22: int64
|
|
|
|
s0 = c0 + a0 * b0
|
|
s1 = c1 + a0 * b1 + a1 * b0
|
|
s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0
|
|
s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0
|
|
s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0
|
|
s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0
|
|
s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 +
|
|
a6 * b0
|
|
s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 +
|
|
a6 * b1 + a7 * b0
|
|
s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 +
|
|
a6 * b2 + a7 * b1 + a8 * b0
|
|
s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 +
|
|
a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0
|
|
s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 +
|
|
a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0
|
|
s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 +
|
|
a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0
|
|
s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + a7 * b5 +
|
|
a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1
|
|
s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + a8 * b5 +
|
|
a9 * b4 + a10 * b3 + a11 * b2
|
|
s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + a9 * b5 +
|
|
a10 * b4 + a11 * b3
|
|
s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + a10 * b5 +
|
|
a11 * b4
|
|
s16 = a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5
|
|
s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6
|
|
s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7
|
|
s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8
|
|
s20 = a9 * b11 + a10 * b10 + a11 * b9
|
|
s21 = a10 * b11 + a11 * b10
|
|
s22 = a11 * b11
|
|
s23 = 0
|
|
|
|
cr0 = ashr((s0 + (1'i64 shl 20)), 21); s1 += cr0; s0 -= cr0 shl 21
|
|
cr2 = ashr((s2 + (1'i64 shl 20)), 21); s3 += cr2; s2 -= cr2 shl 21
|
|
cr4 = ashr((s4 + (1'i64 shl 20)), 21); s5 += cr4; s4 -= cr4 shl 21
|
|
cr6 = ashr((s6 + (1'i64 shl 20)), 21); s7 += cr6; s6 -= cr6 shl 21
|
|
cr8 = ashr((s8 + (1'i64 shl 20)), 21); s9 += cr8; s8 -= cr8 shl 21
|
|
cr10 = ashr((s10 + (1'i64 shl 20)), 21); s11 += cr10; s10 -= cr10 shl 21
|
|
cr12 = ashr((s12 + (1'i64 shl 20)), 21); s13 += cr12; s12 -= cr12 shl 21
|
|
cr14 = ashr((s14 + (1'i64 shl 20)), 21); s15 += cr14; s14 -= cr14 shl 21
|
|
cr16 = ashr((s16 + (1'i64 shl 20)), 21); s17 += cr16; s16 -= cr16 shl 21
|
|
cr18 = ashr((s18 + (1'i64 shl 20)), 21); s19 += cr18; s18 -= cr18 shl 21
|
|
cr20 = ashr((s20 + (1'i64 shl 20)), 21); s21 += cr20; s20 -= cr20 shl 21
|
|
cr22 = ashr((s22 + (1'i64 shl 20)), 21); s23 += cr22; s22 -= cr22 shl 21
|
|
|
|
cr1 = ashr((s1 + (1'i64 shl 20)), 21); s2 += cr1; s1 -= cr1 shl 21
|
|
cr3 = ashr((s3 + (1'i64 shl 20)), 21); s4 += cr3; s3 -= cr3 shl 21
|
|
cr5 = ashr((s5 + (1'i64 shl 20)), 21); s6 += cr5; s5 -= cr5 shl 21
|
|
cr7 = ashr((s7 + (1'i64 shl 20)), 21); s8 += cr7; s7 -= cr7 shl 21
|
|
cr9 = ashr((s9 + (1'i64 shl 20)), 21); s10 += cr9; s9 -= cr9 shl 21
|
|
cr11 = ashr((s11 + (1'i64 shl 20)), 21); s12 += cr11; s11 -= cr11 shl 21
|
|
cr13 = ashr((s13 + (1'i64 shl 20)), 21); s14 += cr13; s13 -= cr13 shl 21
|
|
cr15 = ashr((s15 + (1'i64 shl 20)), 21); s16 += cr15; s15 -= cr15 shl 21
|
|
cr17 = ashr((s17 + (1'i64 shl 20)), 21); s18 += cr17; s17 -= cr17 shl 21
|
|
cr19 = ashr((s19 + (1'i64 shl 20)), 21); s20 += cr19; s19 -= cr19 shl 21
|
|
cr21 = ashr((s21 + (1'i64 shl 20)), 21); s22 += cr21; s21 -= cr21 shl 21
|
|
|
|
s11 += s23 * 666643
|
|
s12 += s23 * 470296
|
|
s13 += s23 * 654183
|
|
s14 -= s23 * 997805
|
|
s15 += s23 * 136657
|
|
s16 -= s23 * 683901
|
|
s23 = 0
|
|
|
|
s10 += s22 * 666643
|
|
s11 += s22 * 470296
|
|
s12 += s22 * 654183
|
|
s13 -= s22 * 997805
|
|
s14 += s22 * 136657
|
|
s15 -= s22 * 683901
|
|
s22 = 0
|
|
|
|
s9 += s21 * 666643
|
|
s10 += s21 * 470296
|
|
s11 += s21 * 654183
|
|
s12 -= s21 * 997805
|
|
s13 += s21 * 136657
|
|
s14 -= s21 * 683901
|
|
s21 = 0
|
|
|
|
s8 += s20 * 666643
|
|
s9 += s20 * 470296
|
|
s10 += s20 * 654183
|
|
s11 -= s20 * 997805
|
|
s12 += s20 * 136657
|
|
s13 -= s20 * 683901
|
|
s20 = 0
|
|
|
|
s7 += s19 * 666643
|
|
s8 += s19 * 470296
|
|
s9 += s19 * 654183
|
|
s10 -= s19 * 997805
|
|
s11 += s19 * 136657
|
|
s12 -= s19 * 683901
|
|
s19 = 0
|
|
|
|
s6 += s18 * 666643
|
|
s7 += s18 * 470296
|
|
s8 += s18 * 654183
|
|
s9 -= s18 * 997805
|
|
s10 += s18 * 136657
|
|
s11 -= s18 * 683901
|
|
s18 = 0
|
|
|
|
cr6 = ashr((s6 + (1'i64 shl 20)), 21); s7 += cr6; s6 -= cr6 shl 21
|
|
cr8 = ashr((s8 + (1'i64 shl 20)), 21); s9 += cr8; s8 -= cr8 shl 21
|
|
cr10 = ashr((s10 + (1'i64 shl 20)), 21); s11 += cr10; s10 -= cr10 shl 21
|
|
cr12 = ashr((s12 + (1'i64 shl 20)), 21); s13 += cr12; s12 -= cr12 shl 21
|
|
cr14 = ashr((s14 + (1'i64 shl 20)), 21); s15 += cr14; s14 -= cr14 shl 21
|
|
cr16 = ashr((s16 + (1'i64 shl 20)), 21); s17 += cr16; s16 -= cr16 shl 21
|
|
|
|
cr7 = ashr((s7 + (1'i64 shl 20)), 21); s8 += cr7; s7 -= cr7 shl 21
|
|
cr9 = ashr((s9 + (1'i64 shl 20)), 21); s10 += cr9; s9 -= cr9 shl 21
|
|
cr11 = ashr((s11 + (1'i64 shl 20)), 21); s12 += cr11; s11 -= cr11 shl 21
|
|
cr13 = ashr((s13 + (1'i64 shl 20)), 21); s14 += cr13; s13 -= cr13 shl 21
|
|
cr15 = ashr((s15 + (1'i64 shl 20)), 21); s16 += cr15; s15 -= cr15 shl 21
|
|
|
|
s5 += s17 * 666643
|
|
s6 += s17 * 470296
|
|
s7 += s17 * 654183
|
|
s8 -= s17 * 997805
|
|
s9 += s17 * 136657
|
|
s10 -= s17 * 683901
|
|
s17 = 0
|
|
|
|
s4 += s16 * 666643
|
|
s5 += s16 * 470296
|
|
s6 += s16 * 654183
|
|
s7 -= s16 * 997805
|
|
s8 += s16 * 136657
|
|
s9 -= s16 * 683901
|
|
s16 = 0
|
|
|
|
s3 += s15 * 666643
|
|
s4 += s15 * 470296
|
|
s5 += s15 * 654183
|
|
s6 -= s15 * 997805
|
|
s7 += s15 * 136657
|
|
s8 -= s15 * 683901
|
|
s15 = 0
|
|
|
|
s2 += s14 * 666643
|
|
s3 += s14 * 470296
|
|
s4 += s14 * 654183
|
|
s5 -= s14 * 997805
|
|
s6 += s14 * 136657
|
|
s7 -= s14 * 683901
|
|
s14 = 0
|
|
|
|
s1 += s13 * 666643
|
|
s2 += s13 * 470296
|
|
s3 += s13 * 654183
|
|
s4 -= s13 * 997805
|
|
s5 += s13 * 136657
|
|
s6 -= s13 * 683901
|
|
s13 = 0
|
|
|
|
s0 += s12 * 666643
|
|
s1 += s12 * 470296
|
|
s2 += s12 * 654183
|
|
s3 -= s12 * 997805
|
|
s4 += s12 * 136657
|
|
s5 -= s12 * 683901
|
|
s12 = 0
|
|
|
|
cr0 = ashr((s0 + (1'i64 shl 20)), 21); s1 += cr0; s0 -= cr0 shl 21
|
|
cr2 = ashr((s2 + (1'i64 shl 20)), 21); s3 += cr2; s2 -= cr2 shl 21
|
|
cr4 = ashr((s4 + (1'i64 shl 20)), 21); s5 += cr4; s4 -= cr4 shl 21
|
|
cr6 = ashr((s6 + (1'i64 shl 20)), 21); s7 += cr6; s6 -= cr6 shl 21
|
|
cr8 = ashr((s8 + (1'i64 shl 20)), 21); s9 += cr8; s8 -= cr8 shl 21
|
|
cr10 = ashr((s10 + (1'i64 shl 20)), 21); s11 += cr10; s10 -= cr10 shl 21
|
|
|
|
cr1 = ashr((s1 + (1'i64 shl 20)), 21); s2 += cr1; s1 -= cr1 shl 21
|
|
cr3 = ashr((s3 + (1'i64 shl 20)), 21); s4 += cr3; s3 -= cr3 shl 21
|
|
cr5 = ashr((s5 + (1'i64 shl 20)), 21); s6 += cr5; s5 -= cr5 shl 21
|
|
cr7 = ashr((s7 + (1'i64 shl 20)), 21); s8 += cr7; s7 -= cr7 shl 21
|
|
cr9 = ashr((s9 + (1'i64 shl 20)), 21); s10 += cr9; s9 -= cr9 shl 21
|
|
cr11 = ashr((s11 + (1'i64 shl 20)), 21); s12 += cr11; s11 -= cr11 shl 21
|
|
|
|
s0 += s12 * 666643
|
|
s1 += s12 * 470296
|
|
s2 += s12 * 654183
|
|
s3 -= s12 * 997805
|
|
s4 += s12 * 136657
|
|
s5 -= s12 * 683901
|
|
s12 = 0
|
|
|
|
cr0 = ashr(s0, 21); s1 += cr0; s0 -= cr0 shl 21
|
|
cr1 = ashr(s1, 21); s2 += cr1; s1 -= cr1 shl 21
|
|
cr2 = ashr(s2, 21); s3 += cr2; s2 -= cr2 shl 21
|
|
cr3 = ashr(s3, 21); s4 += cr3; s3 -= cr3 shl 21
|
|
cr4 = ashr(s4, 21); s5 += cr4; s4 -= cr4 shl 21
|
|
cr5 = ashr(s5, 21); s6 += cr5; s5 -= cr5 shl 21
|
|
cr6 = ashr(s6, 21); s7 += cr6; s6 -= cr6 shl 21
|
|
cr7 = ashr(s7, 21); s8 += cr7; s7 -= cr7 shl 21
|
|
cr8 = ashr(s8, 21); s9 += cr8; s8 -= cr8 shl 21
|
|
cr9 = ashr(s9, 21); s10 += cr9; s9 -= cr9 shl 21
|
|
cr10 = ashr(s10, 21); s11 += cr10; s10 -= cr10 shl 21
|
|
cr11 = ashr(s11, 21); s12 += cr11; s11 -= cr11 shl 21
|
|
|
|
s0 += s12 * 666643
|
|
s1 += s12 * 470296
|
|
s2 += s12 * 654183
|
|
s3 -= s12 * 997805
|
|
s4 += s12 * 136657
|
|
s5 -= s12 * 683901
|
|
s12 = 0
|
|
|
|
cr0 = ashr(s0, 21); s1 += cr0; s0 -= cr0 shl 21
|
|
cr1 = ashr(s1, 21); s2 += cr1; s1 -= cr1 shl 21
|
|
cr2 = ashr(s2, 21); s3 += cr2; s2 -= cr2 shl 21
|
|
cr3 = ashr(s3, 21); s4 += cr3; s3 -= cr3 shl 21
|
|
cr4 = ashr(s4, 21); s5 += cr4; s4 -= cr4 shl 21
|
|
cr5 = ashr(s5, 21); s6 += cr5; s5 -= cr5 shl 21
|
|
cr6 = ashr(s6, 21); s7 += cr6; s6 -= cr6 shl 21
|
|
cr7 = ashr(s7, 21); s8 += cr7; s7 -= cr7 shl 21
|
|
cr8 = ashr(s8, 21); s9 += cr8; s8 -= cr8 shl 21
|
|
cr9 = ashr(s9, 21); s10 += cr9; s9 -= cr9 shl 21
|
|
cr10 = ashr(s10, 21); s11 += cr10; s10 -= cr10 shl 21
|
|
|
|
s[0] = cast[uint8](ashr(s0, 0))
|
|
s[1] = cast[uint8](ashr(s0, 8))
|
|
s[2] = cast[uint8](ashr(s0, 16) or (s1 shl 5))
|
|
s[3] = cast[uint8](ashr(s1, 3))
|
|
s[4] = cast[uint8](ashr(s1, 11))
|
|
s[5] = cast[uint8](ashr(s1, 19) or (s2 shl 2))
|
|
s[6] = cast[uint8](ashr(s2, 6))
|
|
s[7] = cast[uint8](ashr(s2, 14) or (s3 shl 7))
|
|
s[8] = cast[uint8](ashr(s3, 1))
|
|
s[9] = cast[uint8](ashr(s3, 9))
|
|
s[10] = cast[uint8](ashr(s3, 17) or (s4 shl 4))
|
|
s[11] = cast[uint8](ashr(s4, 4))
|
|
s[12] = cast[uint8](ashr(s4, 12))
|
|
s[13] = cast[uint8](ashr(s4, 20) or (s5 shl 1))
|
|
s[14] = cast[uint8](ashr(s5, 7))
|
|
s[15] = cast[uint8](ashr(s5, 15) or (s6 shl 6))
|
|
s[16] = cast[uint8](ashr(s6, 2))
|
|
s[17] = cast[uint8](ashr(s6, 10))
|
|
s[18] = cast[uint8](ashr(s6, 18) or (s7 shl 3))
|
|
s[19] = cast[uint8](ashr(s7, 5))
|
|
s[20] = cast[uint8](ashr(s7, 13))
|
|
s[21] = cast[uint8](ashr(s8, 0))
|
|
s[22] = cast[uint8](ashr(s8, 8))
|
|
s[23] = cast[uint8](ashr(s8, 16) or (s9 shl 5))
|
|
s[24] = cast[uint8](ashr(s9, 3))
|
|
s[25] = cast[uint8](ashr(s9, 11))
|
|
s[26] = cast[uint8](ashr(s9, 19) or (s10 shl 2))
|
|
s[27] = cast[uint8](ashr(s10, 6))
|
|
s[28] = cast[uint8](ashr(s10, 14) or (s11 shl 7))
|
|
s[29] = cast[uint8](ashr(s11, 1))
|
|
s[30] = cast[uint8](ashr(s11, 9))
|
|
s[31] = cast[uint8](ashr(s11, 17))
|
|
|
|
proc scReduce(s: var openArray[byte]) =
|
|
var s0 = 2097151'i64 and cast[int64](load_3(s.toOpenArray(0, 2)));
|
|
var s1 = 2097151'i64 and cast[int64](load_4(s.toOpenArray(2, 5)) shr 5)
|
|
var s2 = 2097151'i64 and cast[int64](load_3(s.toOpenArray(5, 7)) shr 2)
|
|
var s3 = 2097151'i64 and cast[int64](load_4(s.toOpenArray(7, 10)) shr 7)
|
|
var s4 = 2097151'i64 and cast[int64](load_4(s.toOpenArray(10, 13)) shr 4)
|
|
var s5 = 2097151'i64 and cast[int64](load_3(s.toOpenArray(13, 15)) shr 1)
|
|
var s6 = 2097151'i64 and cast[int64](load_4(s.toOpenArray(15, 18)) shr 6)
|
|
var s7 = 2097151'i64 and cast[int64](load_3(s.toOpenArray(18, 20)) shr 3)
|
|
var s8 = 2097151'i64 and cast[int64](load_3(s.toOpenArray(21, 23)))
|
|
var s9 = 2097151'i64 and cast[int64](load_4(s.toOpenArray(23, 26)) shr 5)
|
|
var s10 = 2097151'i64 and cast[int64](load_3(s.toOpenArray(26, 28)) shr 2)
|
|
var s11 = 2097151'i64 and cast[int64](load_4(s.toOpenArray(28, 31)) shr 7)
|
|
var s12 = 2097151'i64 and cast[int64](load_4(s.toOpenArray(31, 34)) shr 4)
|
|
var s13 = 2097151'i64 and cast[int64](load_3(s.toOpenArray(34, 36)) shr 1)
|
|
var s14 = 2097151'i64 and cast[int64](load_4(s.toOpenArray(36, 39)) shr 6)
|
|
var s15 = 2097151'i64 and cast[int64](load_3(s.toOpenArray(39, 42)) shr 3)
|
|
var s16 = 2097151'i64 and cast[int64](load_3(s.toOpenArray(42, 44)))
|
|
var s17 = 2097151'i64 and cast[int64](load_4(s.toOpenArray(44, 47)) shr 5)
|
|
var s18 = 2097151'i64 and cast[int64](load_3(s.toOpenArray(47, 49)) shr 2)
|
|
var s19 = 2097151'i64 and cast[int64](load_4(s.toOpenArray(49, 52)) shr 7)
|
|
var s20 = 2097151'i64 and cast[int64](load_4(s.toOpenArray(52, 55)) shr 4)
|
|
var s21 = 2097151'i64 and cast[int64](load_3(s.toOpenArray(55, 57)) shr 1)
|
|
var s22 = 2097151'i64 and cast[int64](load_4(s.toOpenArray(57, 60)) shr 6)
|
|
var s23 = cast[int64](load_4(s.toOpenArray(60, 63)) shr 3)
|
|
var
|
|
cr0, cr1, cr2, cr3, cr4, cr5, cr6, cr7, cr8: int64
|
|
cr9, cr10, cr11, cr12, cr13, cr14, cr15, cr16: int64
|
|
|
|
s11 += s23 * 666643
|
|
s12 += s23 * 470296
|
|
s13 += s23 * 654183
|
|
s14 -= s23 * 997805
|
|
s15 += s23 * 136657
|
|
s16 -= s23 * 683901
|
|
s23 = 0
|
|
|
|
s10 += s22 * 666643
|
|
s11 += s22 * 470296
|
|
s12 += s22 * 654183
|
|
s13 -= s22 * 997805
|
|
s14 += s22 * 136657
|
|
s15 -= s22 * 683901
|
|
s22 = 0
|
|
|
|
s9 += s21 * 666643
|
|
s10 += s21 * 470296
|
|
s11 += s21 * 654183
|
|
s12 -= s21 * 997805
|
|
s13 += s21 * 136657
|
|
s14 -= s21 * 683901
|
|
s21 = 0
|
|
|
|
s8 += s20 * 666643
|
|
s9 += s20 * 470296
|
|
s10 += s20 * 654183
|
|
s11 -= s20 * 997805
|
|
s12 += s20 * 136657
|
|
s13 -= s20 * 683901
|
|
s20 = 0
|
|
|
|
s7 += s19 * 666643
|
|
s8 += s19 * 470296
|
|
s9 += s19 * 654183
|
|
s10 -= s19 * 997805
|
|
s11 += s19 * 136657
|
|
s12 -= s19 * 683901
|
|
s19 = 0
|
|
|
|
s6 += s18 * 666643
|
|
s7 += s18 * 470296
|
|
s8 += s18 * 654183
|
|
s9 -= s18 * 997805
|
|
s10 += s18 * 136657
|
|
s11 -= s18 * 683901
|
|
s18 = 0
|
|
|
|
cr6 = ashr((s6 + (1'i64 shl 20)), 21); s7 += cr6; s6 -= cr6 shl 21
|
|
cr8 = ashr((s8 + (1'i64 shl 20)), 21); s9 += cr8; s8 -= cr8 shl 21
|
|
cr10 = ashr((s10 + (1'i64 shl 20)), 21); s11 += cr10; s10 -= cr10 shl 21
|
|
cr12 = ashr((s12 + (1'i64 shl 20)), 21); s13 += cr12; s12 -= cr12 shl 21
|
|
cr14 = ashr((s14 + (1'i64 shl 20)), 21); s15 += cr14; s14 -= cr14 shl 21
|
|
cr16 = ashr((s16 + (1'i64 shl 20)), 21); s17 += cr16; s16 -= cr16 shl 21
|
|
|
|
cr7 = ashr((s7 + (1'i64 shl 20)), 21); s8 += cr7; s7 -= cr7 shl 21
|
|
cr9 = ashr((s9 + (1'i64 shl 20)), 21); s10 += cr9; s9 -= cr9 shl 21
|
|
cr11 = ashr((s11 + (1'i64 shl 20)), 21); s12 += cr11; s11 -= cr11 shl 21
|
|
cr13 = ashr((s13 + (1'i64 shl 20)), 21); s14 += cr13; s13 -= cr13 shl 21
|
|
cr15 = ashr((s15 + (1'i64 shl 20)), 21); s16 += cr15; s15 -= cr15 shl 21
|
|
|
|
s5 += s17 * 666643
|
|
s6 += s17 * 470296
|
|
s7 += s17 * 654183
|
|
s8 -= s17 * 997805
|
|
s9 += s17 * 136657
|
|
s10 -= s17 * 683901
|
|
s17 = 0
|
|
|
|
s4 += s16 * 666643
|
|
s5 += s16 * 470296
|
|
s6 += s16 * 654183
|
|
s7 -= s16 * 997805
|
|
s8 += s16 * 136657
|
|
s9 -= s16 * 683901
|
|
s16 = 0
|
|
|
|
s3 += s15 * 666643
|
|
s4 += s15 * 470296
|
|
s5 += s15 * 654183
|
|
s6 -= s15 * 997805
|
|
s7 += s15 * 136657
|
|
s8 -= s15 * 683901
|
|
s15 = 0
|
|
|
|
s2 += s14 * 666643
|
|
s3 += s14 * 470296
|
|
s4 += s14 * 654183
|
|
s5 -= s14 * 997805
|
|
s6 += s14 * 136657
|
|
s7 -= s14 * 683901
|
|
s14 = 0
|
|
|
|
s1 += s13 * 666643
|
|
s2 += s13 * 470296
|
|
s3 += s13 * 654183
|
|
s4 -= s13 * 997805
|
|
s5 += s13 * 136657
|
|
s6 -= s13 * 683901
|
|
s13 = 0
|
|
|
|
s0 += s12 * 666643
|
|
s1 += s12 * 470296
|
|
s2 += s12 * 654183
|
|
s3 -= s12 * 997805
|
|
s4 += s12 * 136657
|
|
s5 -= s12 * 683901
|
|
s12 = 0
|
|
|
|
cr0 = ashr((s0 + (1'i64 shl 20)), 21); s1 += cr0; s0 -= cr0 shl 21
|
|
cr2 = ashr((s2 + (1'i64 shl 20)), 21); s3 += cr2; s2 -= cr2 shl 21
|
|
cr4 = ashr((s4 + (1'i64 shl 20)), 21); s5 += cr4; s4 -= cr4 shl 21
|
|
cr6 = ashr((s6 + (1'i64 shl 20)), 21); s7 += cr6; s6 -= cr6 shl 21
|
|
cr8 = ashr((s8 + (1'i64 shl 20)), 21); s9 += cr8; s8 -= cr8 shl 21
|
|
cr10 = ashr((s10 + (1'i64 shl 20)), 21); s11 += cr10; s10 -= cr10 shl 21
|
|
|
|
cr1 = ashr((s1 + (1'i64 shl 20)), 21); s2 += cr1; s1 -= cr1 shl 21
|
|
cr3 = ashr((s3 + (1'i64 shl 20)), 21); s4 += cr3; s3 -= cr3 shl 21
|
|
cr5 = ashr((s5 + (1'i64 shl 20)), 21); s6 += cr5; s5 -= cr5 shl 21
|
|
cr7 = ashr((s7 + (1'i64 shl 20)), 21); s8 += cr7; s7 -= cr7 shl 21
|
|
cr9 = ashr((s9 + (1'i64 shl 20)), 21); s10 += cr9; s9 -= cr9 shl 21
|
|
cr11 = ashr((s11 + (1'i64 shl 20)), 21); s12 += cr11; s11 -= cr11 shl 21
|
|
|
|
s0 += s12 * 666643
|
|
s1 += s12 * 470296
|
|
s2 += s12 * 654183
|
|
s3 -= s12 * 997805
|
|
s4 += s12 * 136657
|
|
s5 -= s12 * 683901
|
|
s12 = 0;
|
|
|
|
cr0 = ashr(s0, 21); s1 += cr0; s0 -= cr0 shl 21
|
|
cr1 = ashr(s1, 21); s2 += cr1; s1 -= cr1 shl 21
|
|
cr2 = ashr(s2, 21); s3 += cr2; s2 -= cr2 shl 21
|
|
cr3 = ashr(s3, 21); s4 += cr3; s3 -= cr3 shl 21
|
|
cr4 = ashr(s4, 21); s5 += cr4; s4 -= cr4 shl 21
|
|
cr5 = ashr(s5, 21); s6 += cr5; s5 -= cr5 shl 21
|
|
cr6 = ashr(s6, 21); s7 += cr6; s6 -= cr6 shl 21
|
|
cr7 = ashr(s7, 21); s8 += cr7; s7 -= cr7 shl 21
|
|
cr8 = ashr(s8, 21); s9 += cr8; s8 -= cr8 shl 21
|
|
cr9 = ashr(s9, 21); s10 += cr9; s9 -= cr9 shl 21
|
|
cr10 = ashr(s10, 21); s11 += cr10; s10 -= cr10 shl 21
|
|
cr11 = ashr(s11, 21); s12 += cr11; s11 -= cr11 shl 21
|
|
|
|
s0 += s12 * 666643
|
|
s1 += s12 * 470296
|
|
s2 += s12 * 654183
|
|
s3 -= s12 * 997805
|
|
s4 += s12 * 136657
|
|
s5 -= s12 * 683901
|
|
s12 = 0
|
|
|
|
cr0 = ashr(s0, 21); s1 += cr0; s0 -= cr0 shl 21
|
|
cr1 = ashr(s1, 21); s2 += cr1; s1 -= cr1 shl 21
|
|
cr2 = ashr(s2, 21); s3 += cr2; s2 -= cr2 shl 21
|
|
cr3 = ashr(s3, 21); s4 += cr3; s3 -= cr3 shl 21
|
|
cr4 = ashr(s4, 21); s5 += cr4; s4 -= cr4 shl 21
|
|
cr5 = ashr(s5, 21); s6 += cr5; s5 -= cr5 shl 21
|
|
cr6 = ashr(s6, 21); s7 += cr6; s6 -= cr6 shl 21
|
|
cr7 = ashr(s7, 21); s8 += cr7; s7 -= cr7 shl 21
|
|
cr8 = ashr(s8, 21); s9 += cr8; s8 -= cr8 shl 21
|
|
cr9 = ashr(s9, 21); s10 += cr9; s9 -= cr9 shl 21
|
|
cr10 = ashr(s10, 21); s11 += cr10; s10 -= cr10 shl 21
|
|
|
|
s[0] = cast[byte](ashr(s0, 0))
|
|
s[1] = cast[byte](ashr(s0, 8))
|
|
s[2] = cast[byte](ashr(s0, 16) or (s1 shl 5))
|
|
s[3] = cast[byte](ashr(s1, 3))
|
|
s[4] = cast[byte](ashr(s1, 11))
|
|
s[5] = cast[byte](ashr(s1, 19) or (s2 shl 2))
|
|
s[6] = cast[byte](ashr(s2, 6))
|
|
s[7] = cast[byte](ashr(s2, 14) or (s3 shl 7))
|
|
s[8] = cast[byte](ashr(s3, 1))
|
|
s[9] = cast[byte](ashr(s3, 9))
|
|
s[10] = cast[byte](ashr(s3, 17) or (s4 shl 4))
|
|
s[11] = cast[byte](ashr(s4, 4))
|
|
s[12] = cast[byte](ashr(s4, 12))
|
|
s[13] = cast[byte](ashr(s4, 20) or (s5 shl 1))
|
|
s[14] = cast[byte](ashr(s5, 7))
|
|
s[15] = cast[byte](ashr(s5, 15) or (s6 shl 6))
|
|
s[16] = cast[byte](ashr(s6, 2))
|
|
s[17] = cast[byte](ashr(s6, 10))
|
|
s[18] = cast[byte](ashr(s6, 18) or (s7 shl 3))
|
|
s[19] = cast[byte](ashr(s7, 5))
|
|
s[20] = cast[byte](ashr(s7, 13))
|
|
s[21] = cast[byte](ashr(s8, 0))
|
|
s[22] = cast[byte](ashr(s8, 8))
|
|
s[23] = cast[byte](ashr(s8, 16) or (s9 shl 5))
|
|
s[24] = cast[byte](ashr(s9, 3))
|
|
s[25] = cast[byte](ashr(s9, 11))
|
|
s[26] = cast[byte](ashr(s9, 19) or (s10 shl 2))
|
|
s[27] = cast[byte](ashr(s10, 6))
|
|
s[28] = cast[byte](ashr(s10, 14) or (s11 shl 7))
|
|
s[29] = cast[byte](ashr(s11, 1))
|
|
s[30] = cast[byte](ashr(s11, 9))
|
|
s[31] = cast[byte](ashr(s11, 17))
|
|
|
|
proc slide(r: var openArray[int8], a: openArray[byte]) =
|
|
for i in 0..<256:
|
|
r[i] = cast[int8](1'u8 and (a[i shr 3] shr (i and 7)))
|
|
for i in 0..<256:
|
|
if r[i] != 0'i8:
|
|
var b = 1
|
|
while (b <= 6) and (i + b < 256):
|
|
if r[i + b] != 0'i8:
|
|
if r[i] + (r[i + b] shl b) <= 15:
|
|
r[i] += r[i + b] shl b; r[i + b] = 0'i8
|
|
elif (r[i] - (r[i + b] shl b)) >= -15:
|
|
r[i] -= r[i + b] shl b
|
|
for k in (i + b)..<256:
|
|
if r[k] == 0'i8:
|
|
r[k] = 1'i8
|
|
break
|
|
r[k] = 0'i8
|
|
else:
|
|
break
|
|
inc(b)
|
|
|
|
proc geDoubleScalarMultVartime(r: var GeP2, a: openArray[byte], A: GeP3,
|
|
b: openArray[byte]) =
|
|
var
|
|
aslide: array[256, int8]
|
|
bslide: array[256, int8]
|
|
ai: array[8, GeCached]
|
|
t: GeP1P1
|
|
u: GeP3
|
|
a2: GeP3
|
|
|
|
slide(aslide, a)
|
|
slide(bslide, b)
|
|
|
|
geP3ToCached(ai[0], A)
|
|
geP3dbl(t, A); geP1P1toP3(a2, t)
|
|
geAdd(t, a2, ai[0]); geP1P1toP3(u, t); geP3ToCached(ai[1], u)
|
|
geAdd(t, a2, ai[1]); geP1P1toP3(u, t); geP3ToCached(ai[2], u)
|
|
geAdd(t, a2, ai[2]); geP1P1toP3(u, t); geP3ToCached(ai[3], u)
|
|
geAdd(t, a2, ai[3]); geP1P1toP3(u, t); geP3ToCached(ai[4], u)
|
|
geAdd(t, a2, ai[4]); geP1P1toP3(u, t); geP3ToCached(ai[5], u)
|
|
geAdd(t, a2, ai[5]); geP1P1toP3(u, t); geP3ToCached(ai[6], u)
|
|
geAdd(t, a2, ai[6]); geP1P1toP3(u, t); geP3ToCached(ai[7], u)
|
|
geP20(r)
|
|
|
|
var k = 255
|
|
while k >= 0:
|
|
if (aslide[k] != 0) or (bslide[k] != 0):
|
|
break
|
|
dec(k)
|
|
|
|
while k >= 0:
|
|
geP2dbl(t, r)
|
|
if aslide[k] > 0:
|
|
geP1P1toP3(u, t)
|
|
geAdd(t, u, ai[aslide[k] div 2])
|
|
elif aslide[k] < 0:
|
|
geP1P1toP3(u, t)
|
|
geSub(t, u, ai[(-aslide[k]) div 2])
|
|
if bslide[k] > 0:
|
|
geP1P1toP3(u, t)
|
|
geMadd(t, u, BiPrecomp[bslide[k] div 2])
|
|
elif bslide[k] < 0:
|
|
geP1P1toP3(u, t)
|
|
geMsub(t, u, BiPrecomp[(-bslide[k]) div 2])
|
|
geP1P1toP2(r, t)
|
|
dec(k)
|
|
|
|
proc GT(x, y: uint32): uint32 {.inline.} =
|
|
var z = cast[uint32](y - x)
|
|
result = (z xor ((x xor y) and (x xor z))) shr 31
|
|
|
|
proc CMP(x, y: uint32): int32 {.inline.} =
|
|
cast[int32](GT(x, y)) or -(cast[int32](GT(y, x)))
|
|
|
|
proc EQ0(x: int32): uint32 {.inline.} =
|
|
var q = cast[uint32](x)
|
|
result = not(q or -q) shr 31
|
|
|
|
proc NEQ(x, y: uint32): uint32 {.inline.} =
|
|
var q = cast[uint32](x xor y)
|
|
result = ((q or -q) shr 31)
|
|
|
|
proc LT0(x: int32): uint32 {.inline.} =
|
|
result = cast[uint32](x) shr 31
|
|
|
|
proc checkScalar*(scalar: openArray[byte]): uint32 =
|
|
var z = 0'u32
|
|
var c = 0'i32
|
|
for u in scalar:
|
|
z = z or u
|
|
if len(scalar) == len(CurveOrder):
|
|
for i in countdown(scalar.high, 0):
|
|
c = c or (-(cast[int32](EQ0(c))) and CMP(scalar[i], CurveOrder[i]))
|
|
else:
|
|
c = -1
|
|
result = NEQ(z, 0'u32) and LT0(c)
|
|
|
|
proc random*(t: typedesc[EdPrivateKey], rng: var HmacDrbgContext): EdPrivateKey =
|
|
## Generate new random ED25519 private key using the given random number generator
|
|
var
|
|
point: GeP3
|
|
pk: array[EdPublicKeySize, byte]
|
|
res: EdPrivateKey
|
|
|
|
hmacDrbgGenerate(rng, res.data.toOpenArray(0, 31))
|
|
|
|
var hh = sha512.digest(res.data.toOpenArray(0, 31))
|
|
hh.data[0] = hh.data[0] and 0xF8'u8
|
|
hh.data[31] = hh.data[31] and 0x3F'u8
|
|
hh.data[31] = hh.data[31] or 0x40'u8
|
|
geScalarMultBase(point, hh.data)
|
|
geP3ToBytes(pk, point)
|
|
res.data[32..63] = pk
|
|
|
|
res
|
|
|
|
proc random*(t: typedesc[EdKeyPair], rng: var HmacDrbgContext): EdKeyPair =
|
|
## Generate new random ED25519 private and public keypair using OS specific
|
|
## CSPRNG.
|
|
var
|
|
point: GeP3
|
|
res: EdKeyPair
|
|
|
|
hmacDrbgGenerate(rng, res.seckey.data.toOpenArray(0, 31))
|
|
|
|
var hh = sha512.digest(res.seckey.data.toOpenArray(0, 31))
|
|
hh.data[0] = hh.data[0] and 0xF8'u8
|
|
hh.data[31] = hh.data[31] and 0x3F'u8
|
|
hh.data[31] = hh.data[31] or 0x40'u8
|
|
geScalarMultBase(point, hh.data)
|
|
geP3ToBytes(res.pubkey.data, point)
|
|
res.seckey.data[32..63] = res.pubkey.data
|
|
|
|
res
|
|
|
|
proc getPublicKey*(key: EdPrivateKey): EdPublicKey =
|
|
## Calculate and return ED25519 public key from private key ``key``.
|
|
copyMem(addr result.data[0], unsafeAddr key.data[32], 32)
|
|
|
|
proc toBytes*(key: EdPrivateKey, data: var openArray[byte]): int =
|
|
## Serialize ED25519 `private key` ``key`` to raw binary form and store it
|
|
## to ``data``.
|
|
##
|
|
## Procedure returns number of bytes (octets) needed to store
|
|
## ED25519 private key.
|
|
result = len(key.data)
|
|
if len(data) >= result:
|
|
copyMem(addr data[0], unsafeAddr key.data[0], len(key.data))
|
|
|
|
proc toBytes*(key: EdPublicKey, data: var openArray[byte]): int =
|
|
## Serialize ED25519 `public key` ``key`` to raw binary form and store it
|
|
## to ``data``.
|
|
##
|
|
## Procedure returns number of bytes (octets) needed to store
|
|
## ED25519 public key.
|
|
result = len(key.data)
|
|
if len(data) >= result:
|
|
copyMem(addr data[0], unsafeAddr key.data[0], len(key.data))
|
|
|
|
proc toBytes*(sig: EdSignature, data: var openArray[byte]): int =
|
|
## Serialize ED25519 `signature` ``sig`` to raw binary form and store it
|
|
## to ``data``.
|
|
##
|
|
## Procedure returns number of bytes (octets) needed to store
|
|
## ED25519 signature.
|
|
result = len(sig.data)
|
|
if len(data) >= result:
|
|
copyMem(addr data[0], unsafeAddr sig.data[0], len(sig.data))
|
|
|
|
proc getBytes*(key: EdPrivateKey): seq[byte] = @(key.data)
|
|
## Serialize ED25519 `private key` and return it.
|
|
|
|
proc getBytes*(key: EdPublicKey): seq[byte] = @(key.data)
|
|
## Serialize ED25519 `public key` and return it.
|
|
|
|
proc getBytes*(sig: EdSignature): seq[byte] = @(sig.data)
|
|
## Serialize ED25519 `signature` and return it.
|
|
|
|
proc `==`*(eda, edb: EdPrivateKey): bool =
|
|
## Compare ED25519 `private key` objects for equality.
|
|
result = CT.isEqual(eda.data, edb.data)
|
|
|
|
proc `==`*(eda, edb: EdPublicKey): bool =
|
|
## Compare ED25519 `public key` objects for equality.
|
|
result = CT.isEqual(eda.data, edb.data)
|
|
|
|
proc `==`*(eda, edb: EdSignature): bool =
|
|
## Compare ED25519 `signature` objects for equality.
|
|
result = CT.isEqual(eda.data, edb.data)
|
|
|
|
proc `$`*(key: EdPrivateKey): string =
|
|
## Return string representation of ED25519 `private key`.
|
|
ncrutils.toHex(key.data)
|
|
|
|
proc `$`*(key: EdPublicKey): string =
|
|
## Return string representation of ED25519 `private key`.
|
|
ncrutils.toHex(key.data)
|
|
|
|
proc `$`*(sig: EdSignature): string =
|
|
## Return string representation of ED25519 `signature`.
|
|
ncrutils.toHex(sig.data)
|
|
|
|
proc init*(key: var EdPrivateKey, data: openArray[byte]): bool =
|
|
## Initialize ED25519 `private key` ``key`` from raw binary
|
|
## representation ``data``.
|
|
##
|
|
## Procedure returns ``true`` on success.
|
|
let length = EdPrivateKeySize
|
|
if len(data) >= length:
|
|
copyMem(addr key.data[0], unsafeAddr data[0], length)
|
|
result = true
|
|
|
|
proc init*(key: var EdPublicKey, data: openArray[byte]): bool =
|
|
## Initialize ED25519 `public key` ``key`` from raw binary
|
|
## representation ``data``.
|
|
##
|
|
## Procedure returns ``true`` on success.
|
|
let length = EdPublicKeySize
|
|
if len(data) >= length:
|
|
copyMem(addr key.data[0], unsafeAddr data[0], length)
|
|
result = true
|
|
|
|
proc init*(sig: var EdSignature, data: openArray[byte]): bool =
|
|
## Initialize ED25519 `signature` ``sig`` from raw binary
|
|
## representation ``data``.
|
|
##
|
|
## Procedure returns ``true`` on success.
|
|
let length = EdSignatureSize
|
|
if len(data) >= length:
|
|
copyMem(addr sig.data[0], unsafeAddr data[0], length)
|
|
result = true
|
|
|
|
proc init*(key: var EdPrivateKey, data: string): bool =
|
|
## Initialize ED25519 `private key` ``key`` from hexadecimal string
|
|
## representation ``data``.
|
|
##
|
|
## Procedure returns ``true`` on success.
|
|
init(key, ncrutils.fromHex(data))
|
|
|
|
proc init*(key: var EdPublicKey, data: string): bool =
|
|
## Initialize ED25519 `public key` ``key`` from hexadecimal string
|
|
## representation ``data``.
|
|
##
|
|
## Procedure returns ``true`` on success.
|
|
init(key, ncrutils.fromHex(data))
|
|
|
|
proc init*(sig: var EdSignature, data: string): bool =
|
|
## Initialize ED25519 `signature` ``sig`` from hexadecimal string
|
|
## representation ``data``.
|
|
##
|
|
## Procedure returns ``true`` on success.
|
|
init(sig, ncrutils.fromHex(data))
|
|
|
|
proc init*(t: typedesc[EdPrivateKey],
|
|
data: openArray[byte]): Result[EdPrivateKey, EdError] =
|
|
## Initialize ED25519 `private key` from raw binary representation ``data``
|
|
## and return constructed object.
|
|
var res: t
|
|
if not init(res, data):
|
|
err(EdIncorrectError)
|
|
else:
|
|
ok(res)
|
|
|
|
proc init*(t: typedesc[EdPublicKey],
|
|
data: openArray[byte]): Result[EdPublicKey, EdError] =
|
|
## Initialize ED25519 `public key` from raw binary representation ``data``
|
|
## and return constructed object.
|
|
var res: t
|
|
if not init(res, data):
|
|
err(EdIncorrectError)
|
|
else:
|
|
ok(res)
|
|
|
|
proc init*(t: typedesc[EdSignature],
|
|
data: openArray[byte]): Result[EdSignature, EdError] =
|
|
## Initialize ED25519 `signature` from raw binary representation ``data``
|
|
## and return constructed object.
|
|
var res: t
|
|
if not init(res, data):
|
|
err(EdIncorrectError)
|
|
else:
|
|
ok(res)
|
|
|
|
proc init*(t: typedesc[EdPrivateKey],
|
|
data: string): Result[EdPrivateKey, EdError] =
|
|
## Initialize ED25519 `private key` from hexadecimal string representation
|
|
## ``data`` and return constructed object.
|
|
var res: t
|
|
if not init(res, data):
|
|
err(EdIncorrectError)
|
|
else:
|
|
ok(res)
|
|
|
|
proc init*(t: typedesc[EdPublicKey],
|
|
data: string): Result[EdPublicKey, EdError] =
|
|
## Initialize ED25519 `public key` from hexadecimal string representation
|
|
## ``data`` and return constructed object.
|
|
var res: t
|
|
if not init(res, data):
|
|
err(EdIncorrectError)
|
|
else:
|
|
ok(res)
|
|
|
|
proc init*(t: typedesc[EdSignature],
|
|
data: string): Result[EdSignature, EdError] =
|
|
## Initialize ED25519 `signature` from hexadecimal string representation
|
|
## ``data`` and return constructed object.
|
|
var res: t
|
|
if not init(res, data):
|
|
err(EdIncorrectError)
|
|
else:
|
|
ok(res)
|
|
|
|
proc clear*(key: var EdPrivateKey) =
|
|
## Wipe and clear memory of ED25519 `private key`.
|
|
burnMem(key.data)
|
|
|
|
proc clear*(key: var EdPublicKey) =
|
|
## Wipe and clear memory of ED25519 `public key`.
|
|
burnMem(key.data)
|
|
|
|
proc clear*(sig: var EdSignature) =
|
|
## Wipe and clear memory of ED25519 `signature`.
|
|
burnMem(sig.data)
|
|
|
|
proc clear*(pair: var EdKeyPair) =
|
|
## Wipe and clear memory of ED25519 `key pair`.
|
|
burnMem(pair.seckey.data)
|
|
burnMem(pair.pubkey.data)
|
|
|
|
proc sign*[T: byte|char](key: EdPrivateKey,
|
|
message: openArray[T]): EdSignature {.gcsafe, noinit.} =
|
|
## Create ED25519 signature of data ``message`` using private key ``key``.
|
|
var ctx: sha512
|
|
var r: GeP3
|
|
|
|
ctx.init()
|
|
ctx.update(key.data.toOpenArray(0, 31))
|
|
var hash = ctx.finish()
|
|
|
|
hash.data[0] = hash.data[0] and 0xF8'u8
|
|
hash.data[31] = hash.data[31] and 0x3F'u8
|
|
hash.data[31] = hash.data[31] or 0x40'u8
|
|
|
|
ctx.init()
|
|
ctx.update(hash.data.toOpenArray(32, 63))
|
|
ctx.update(message)
|
|
var nonce = ctx.finish()
|
|
|
|
scReduce(nonce.data)
|
|
geScalarMultBase(r, nonce.data)
|
|
geP3ToBytes(result.data.toOpenArray(0, 31), r)
|
|
|
|
ctx.init()
|
|
ctx.update(result.data.toOpenArray(0, 31))
|
|
ctx.update(key.data.toOpenArray(32, 63))
|
|
ctx.update(message)
|
|
var hram = ctx.finish()
|
|
ctx.clear()
|
|
|
|
scReduce(hram.data)
|
|
scMulAdd(result.data.toOpenArray(32, 63), hram.data.toOpenArray(0, 31),
|
|
hash.data.toOpenArray(0, 31), nonce.data.toOpenArray(0, 31))
|
|
|
|
proc verify*[T: byte|char](sig: EdSignature, message: openArray[T],
|
|
key: EdPublicKey): bool =
|
|
## Verify ED25519 signature ``sig`` using public key ``key`` and data
|
|
## ``message``.
|
|
##
|
|
## Return ``true`` if message verification succeeded, ``false`` if
|
|
## verification failed.
|
|
var ctx: sha512
|
|
var rcheck: array[32, byte]
|
|
var a: GeP3
|
|
var r: GeP2
|
|
if (sig.data[63] and 0xE0'u8) != 0:
|
|
return false
|
|
|
|
if checkScalar(sig.data.toOpenArray(32, 63)) == 0:
|
|
return false
|
|
if geFromBytesNegateVartime(a, key.data.toOpenArray(0, 31)) != 0:
|
|
return false
|
|
|
|
ctx.init()
|
|
ctx.update(sig.data.toOpenArray(0, 31))
|
|
ctx.update(key.data.toOpenArray(0, 31))
|
|
ctx.update(message)
|
|
var hash = ctx.finish()
|
|
scReduce(hash.data)
|
|
|
|
geDoubleScalarMultVartime(r, hash.data.toOpenArray(0, 31),
|
|
a, sig.data.toOpenArray(32, 63))
|
|
geToBytes(rcheck, r)
|
|
|
|
result = (verify32(sig.data.toOpenArray(0, 31), rcheck) == 0)
|