Prad Nukala 807b2e86ec
feature/1220 origin handle exists method (#1241)
* feat: add docs and CI workflow for publishing to onsonr.dev

* (refactor): Move hway,motr executables to their own repos

* feat: simplify devnet and testnet configurations

* refactor: update import path for didcrypto package

* docs(networks): Add README with project overview, architecture, and community links

* refactor: Move network configurations to deploy directory

* build: update golang version to 1.23

* refactor: move logger interface to appropriate package

* refactor: Move devnet configuration to networks/devnet

* chore: improve release process with date variable

* (chore): Move Crypto Library

* refactor: improve code structure and readability in DID module

* feat: integrate Trunk CI checks

* ci: optimize CI workflow by removing redundant build jobs

---------

Co-authored-by: Darp Alakun <i@prad.nu>
2025-01-06 17:06:10 +00:00

417 lines
13 KiB
Go
Executable File

package bls12381
import (
"encoding/binary"
"math/big"
"sync"
"github.com/onsonr/sonr/crypto/core/curves/native"
)
type Fq [native.FieldLimbs]uint64
var (
bls12381FqInitonce sync.Once
bls12381FqParams native.FieldParams
)
// 2^S * t = MODULUS - 1 with t odd
const fqS = 32
// qInv = -(q^{-1} mod 2^64) mod 2^64
const qInv = 0xfffffffeffffffff
// fqGenerator = 7 (multiplicative fqGenerator of r-1 order, that is also quadratic nonresidue)
var fqGenerator = [native.FieldLimbs]uint64{0x0000000efffffff1, 0x17e363d300189c0f, 0xff9c57876f8457b0, 0x351332208fc5a8c4}
// fqModulus
var fqModulus = [native.FieldLimbs]uint64{0xffffffff00000001, 0x53bda402fffe5bfe, 0x3339d80809a1d805, 0x73eda753299d7d48}
func Bls12381FqNew() *native.Field {
return &native.Field{
Value: [native.FieldLimbs]uint64{},
Params: getBls12381FqParams(),
Arithmetic: bls12381FqArithmetic{},
}
}
func bls12381FqParamsInit() {
bls12381FqParams = native.FieldParams{
R: [native.FieldLimbs]uint64{0x00000001fffffffe, 0x5884b7fa00034802, 0x998c4fefecbc4ff5, 0x1824b159acc5056f},
R2: [native.FieldLimbs]uint64{0xc999e990f3f29c6d, 0x2b6cedcb87925c23, 0x05d314967254398f, 0x0748d9d99f59ff11},
R3: [native.FieldLimbs]uint64{0xc62c1807439b73af, 0x1b3e0d188cf06990, 0x73d13c71c7b5f418, 0x6e2a5bb9c8db33e9},
Modulus: [native.FieldLimbs]uint64{0xffffffff00000001, 0x53bda402fffe5bfe, 0x3339d80809a1d805, 0x73eda753299d7d48},
BiModulus: new(big.Int).SetBytes([]byte{
0x73, 0xed, 0xa7, 0x53, 0x29, 0x9d, 0x7d, 0x48, 0x33, 0x39, 0xd8, 0x08, 0x09, 0xa1, 0xd8, 0x05, 0x53, 0xbd, 0xa4, 0x02, 0xff, 0xfe, 0x5b, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
}),
}
}
func getBls12381FqParams() *native.FieldParams {
bls12381FqInitonce.Do(bls12381FqParamsInit)
return &bls12381FqParams
}
// bls12381FqArithmetic is a struct with all the methods needed for working
// in mod q
type bls12381FqArithmetic struct{}
// ToMontgomery converts this field to montgomery form
func (f bls12381FqArithmetic) ToMontgomery(out, arg *[native.FieldLimbs]uint64) {
// arg.R^0 * R^2 / R = arg.R
f.Mul(out, arg, &getBls12381FqParams().R2)
}
// FromMontgomery converts this field from montgomery form
func (f bls12381FqArithmetic) FromMontgomery(out, arg *[native.FieldLimbs]uint64) {
// Mul by 1 is division by 2^256 mod q
// f.Mul(out, arg, &[native.FieldLimbs]uint64{1, 0, 0, 0})
f.montReduce(out, &[native.FieldLimbs * 2]uint64{arg[0], arg[1], arg[2], arg[3], 0, 0, 0, 0})
}
// Neg performs modular negation
func (f bls12381FqArithmetic) Neg(out, arg *[native.FieldLimbs]uint64) {
// Subtract `arg` from `fqModulus`. Ignore final borrow
// since it can't underflow.
var t [native.FieldLimbs]uint64
var borrow uint64
t[0], borrow = sbb(fqModulus[0], arg[0], 0)
t[1], borrow = sbb(fqModulus[1], arg[1], borrow)
t[2], borrow = sbb(fqModulus[2], arg[2], borrow)
t[3], _ = sbb(fqModulus[3], arg[3], borrow)
// t could be `fqModulus` if `arg`=0. Set mask=0 if self=0
// and 0xff..ff if `arg`!=0
mask := t[0] | t[1] | t[2] | t[3]
mask = -((mask | -mask) >> 63)
out[0] = t[0] & mask
out[1] = t[1] & mask
out[2] = t[2] & mask
out[3] = t[3] & mask
}
// Square performs modular square
func (f bls12381FqArithmetic) Square(out, arg *[native.FieldLimbs]uint64) {
var r [2 * native.FieldLimbs]uint64
var carry uint64
r[1], carry = mac(0, arg[0], arg[1], 0)
r[2], carry = mac(0, arg[0], arg[2], carry)
r[3], r[4] = mac(0, arg[0], arg[3], carry)
r[3], carry = mac(r[3], arg[1], arg[2], 0)
r[4], r[5] = mac(r[4], arg[1], arg[3], carry)
r[5], r[6] = mac(r[5], arg[2], arg[3], 0)
r[7] = r[6] >> 63
r[6] = (r[6] << 1) | r[5]>>63
r[5] = (r[5] << 1) | r[4]>>63
r[4] = (r[4] << 1) | r[3]>>63
r[3] = (r[3] << 1) | r[2]>>63
r[2] = (r[2] << 1) | r[1]>>63
r[1] = r[1] << 1
r[0], carry = mac(0, arg[0], arg[0], 0)
r[1], carry = adc(0, r[1], carry)
r[2], carry = mac(r[2], arg[1], arg[1], carry)
r[3], carry = adc(0, r[3], carry)
r[4], carry = mac(r[4], arg[2], arg[2], carry)
r[5], carry = adc(0, r[5], carry)
r[6], carry = mac(r[6], arg[3], arg[3], carry)
r[7], _ = adc(0, r[7], carry)
f.montReduce(out, &r)
}
// Mul performs modular multiplication
func (f bls12381FqArithmetic) Mul(out, arg1, arg2 *[native.FieldLimbs]uint64) {
// Schoolbook multiplication
var r [2 * native.FieldLimbs]uint64
var carry uint64
r[0], carry = mac(0, arg1[0], arg2[0], 0)
r[1], carry = mac(0, arg1[0], arg2[1], carry)
r[2], carry = mac(0, arg1[0], arg2[2], carry)
r[3], r[4] = mac(0, arg1[0], arg2[3], carry)
r[1], carry = mac(r[1], arg1[1], arg2[0], 0)
r[2], carry = mac(r[2], arg1[1], arg2[1], carry)
r[3], carry = mac(r[3], arg1[1], arg2[2], carry)
r[4], r[5] = mac(r[4], arg1[1], arg2[3], carry)
r[2], carry = mac(r[2], arg1[2], arg2[0], 0)
r[3], carry = mac(r[3], arg1[2], arg2[1], carry)
r[4], carry = mac(r[4], arg1[2], arg2[2], carry)
r[5], r[6] = mac(r[5], arg1[2], arg2[3], carry)
r[3], carry = mac(r[3], arg1[3], arg2[0], 0)
r[4], carry = mac(r[4], arg1[3], arg2[1], carry)
r[5], carry = mac(r[5], arg1[3], arg2[2], carry)
r[6], r[7] = mac(r[6], arg1[3], arg2[3], carry)
f.montReduce(out, &r)
}
// Add performs modular addition
func (f bls12381FqArithmetic) Add(out, arg1, arg2 *[native.FieldLimbs]uint64) {
var t [native.FieldLimbs]uint64
var carry uint64
t[0], carry = adc(arg1[0], arg2[0], 0)
t[1], carry = adc(arg1[1], arg2[1], carry)
t[2], carry = adc(arg1[2], arg2[2], carry)
t[3], _ = adc(arg1[3], arg2[3], carry)
// Subtract the fqModulus to ensure the value
// is smaller.
f.Sub(out, &t, &fqModulus)
}
// Sub performs modular subtraction
func (f bls12381FqArithmetic) Sub(out, arg1, arg2 *[native.FieldLimbs]uint64) {
d0, borrow := sbb(arg1[0], arg2[0], 0)
d1, borrow := sbb(arg1[1], arg2[1], borrow)
d2, borrow := sbb(arg1[2], arg2[2], borrow)
d3, borrow := sbb(arg1[3], arg2[3], borrow)
// If underflow occurred on the final limb, borrow 0xff...ff, otherwise
// borrow = 0x00...00. Conditionally mask to add the fqModulus
borrow = -borrow
d0, carry := adc(d0, fqModulus[0]&borrow, 0)
d1, carry = adc(d1, fqModulus[1]&borrow, carry)
d2, carry = adc(d2, fqModulus[2]&borrow, carry)
d3, _ = adc(d3, fqModulus[3]&borrow, carry)
out[0] = d0
out[1] = d1
out[2] = d2
out[3] = d3
}
// Sqrt performs modular square root
func (f bls12381FqArithmetic) Sqrt(wasSquare *int, out, arg *[native.FieldLimbs]uint64) {
// See sqrt_ts_ct at
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#appendix-I.4
// c1 := fqS
// c2 := (q - 1) / (2^c1)
c2 := [4]uint64{
0xfffe5bfeffffffff,
0x09a1d80553bda402,
0x299d7d483339d808,
0x0000000073eda753,
}
// c3 := (c2 - 1) / 2
c3 := [native.FieldLimbs]uint64{
0x7fff2dff7fffffff,
0x04d0ec02a9ded201,
0x94cebea4199cec04,
0x0000000039f6d3a9,
}
// c4 := fqGenerator
var c5 [native.FieldLimbs]uint64
native.Pow(&c5, &fqGenerator, &c2, getBls12381FqParams(), f)
// c5 := [native.FieldLimbs]uint64{0x1015708f7e368fe1, 0x31c6c5456ecc4511, 0x5281fe8998a19ea1, 0x0279089e10c63fe8}
var z, t, b, c, tv [native.FieldLimbs]uint64
native.Pow(&z, arg, &c3, getBls12381FqParams(), f)
f.Square(&t, &z)
f.Mul(&t, &t, arg)
f.Mul(&z, &z, arg)
copy(b[:], t[:])
copy(c[:], c5[:])
for i := fqS; i >= 2; i-- {
for j := 1; j <= i-2; j++ {
f.Square(&b, &b)
}
// if b == 1 flag = 0 else flag = 1
flag := -(&native.Field{
Value: b,
Params: getBls12381FqParams(),
Arithmetic: f,
}).IsOne() + 1
f.Mul(&tv, &z, &c)
f.Selectznz(&z, &z, &tv, flag)
f.Square(&c, &c)
f.Mul(&tv, &t, &c)
f.Selectznz(&t, &t, &tv, flag)
copy(b[:], t[:])
}
f.Square(&c, &z)
*wasSquare = (&native.Field{
Value: c,
Params: getBls12381FqParams(),
Arithmetic: f,
}).Equal(&native.Field{
Value: *arg,
Params: getBls12381FqParams(),
Arithmetic: f,
})
f.Selectznz(out, out, &z, *wasSquare)
}
// Invert performs modular inverse
func (f bls12381FqArithmetic) Invert(wasInverted *int, out, arg *[native.FieldLimbs]uint64) {
// Using an addition chain from
// https://github.com/kwantam/addchain
var t0, t1, t2, t3, t4, t5, t6, t7, t8 [native.FieldLimbs]uint64
var t9, t11, t12, t13, t14, t15, t16, t17 [native.FieldLimbs]uint64
f.Square(&t0, arg)
f.Mul(&t1, &t0, arg)
f.Square(&t16, &t0)
f.Square(&t6, &t16)
f.Mul(&t5, &t6, &t0)
f.Mul(&t0, &t6, &t16)
f.Mul(&t12, &t5, &t16)
f.Square(&t2, &t6)
f.Mul(&t7, &t5, &t6)
f.Mul(&t15, &t0, &t5)
f.Square(&t17, &t12)
f.Mul(&t1, &t1, &t17)
f.Mul(&t3, &t7, &t2)
f.Mul(&t8, &t1, &t17)
f.Mul(&t4, &t8, &t2)
f.Mul(&t9, &t8, &t7)
f.Mul(&t7, &t4, &t5)
f.Mul(&t11, &t4, &t17)
f.Mul(&t5, &t9, &t17)
f.Mul(&t14, &t7, &t15)
f.Mul(&t13, &t11, &t12)
f.Mul(&t12, &t11, &t17)
f.Mul(&t15, &t15, &t12)
f.Mul(&t16, &t16, &t15)
f.Mul(&t3, &t3, &t16)
f.Mul(&t17, &t17, &t3)
f.Mul(&t0, &t0, &t17)
f.Mul(&t6, &t6, &t0)
f.Mul(&t2, &t2, &t6)
native.Pow2k(&t0, &t0, 8, f)
f.Mul(&t0, &t0, &t17)
native.Pow2k(&t0, &t0, 9, f)
f.Mul(&t0, &t0, &t16)
native.Pow2k(&t0, &t0, 9, f)
f.Mul(&t0, &t0, &t15)
native.Pow2k(&t0, &t0, 9, f)
f.Mul(&t0, &t0, &t15)
native.Pow2k(&t0, &t0, 7, f)
f.Mul(&t0, &t0, &t14)
native.Pow2k(&t0, &t0, 7, f)
f.Mul(&t0, &t0, &t13)
native.Pow2k(&t0, &t0, 10, f)
f.Mul(&t0, &t0, &t12)
native.Pow2k(&t0, &t0, 9, f)
f.Mul(&t0, &t0, &t11)
native.Pow2k(&t0, &t0, 8, f)
f.Mul(&t0, &t0, &t8)
native.Pow2k(&t0, &t0, 8, f)
f.Mul(&t0, &t0, arg)
native.Pow2k(&t0, &t0, 14, f)
f.Mul(&t0, &t0, &t9)
native.Pow2k(&t0, &t0, 10, f)
f.Mul(&t0, &t0, &t8)
native.Pow2k(&t0, &t0, 15, f)
f.Mul(&t0, &t0, &t7)
native.Pow2k(&t0, &t0, 10, f)
f.Mul(&t0, &t0, &t6)
native.Pow2k(&t0, &t0, 8, f)
f.Mul(&t0, &t0, &t5)
native.Pow2k(&t0, &t0, 16, f)
f.Mul(&t0, &t0, &t3)
native.Pow2k(&t0, &t0, 8, f)
f.Mul(&t0, &t0, &t2)
native.Pow2k(&t0, &t0, 7, f)
f.Mul(&t0, &t0, &t4)
native.Pow2k(&t0, &t0, 9, f)
f.Mul(&t0, &t0, &t2)
native.Pow2k(&t0, &t0, 8, f)
f.Mul(&t0, &t0, &t3)
native.Pow2k(&t0, &t0, 8, f)
f.Mul(&t0, &t0, &t2)
native.Pow2k(&t0, &t0, 8, f)
f.Mul(&t0, &t0, &t2)
native.Pow2k(&t0, &t0, 8, f)
f.Mul(&t0, &t0, &t2)
native.Pow2k(&t0, &t0, 8, f)
f.Mul(&t0, &t0, &t3)
native.Pow2k(&t0, &t0, 8, f)
f.Mul(&t0, &t0, &t2)
native.Pow2k(&t0, &t0, 8, f)
f.Mul(&t0, &t0, &t2)
native.Pow2k(&t0, &t0, 5, f)
f.Mul(&t0, &t0, &t1)
native.Pow2k(&t0, &t0, 5, f)
f.Mul(&t0, &t0, &t1)
*wasInverted = (&native.Field{
Value: *arg,
Params: getBls12381FqParams(),
Arithmetic: f,
}).IsNonZero()
f.Selectznz(out, out, &t0, *wasInverted)
}
// FromBytes converts a little endian byte array into a field element
func (f bls12381FqArithmetic) FromBytes(out *[native.FieldLimbs]uint64, arg *[native.FieldBytes]byte) {
out[0] = binary.LittleEndian.Uint64(arg[:8])
out[1] = binary.LittleEndian.Uint64(arg[8:16])
out[2] = binary.LittleEndian.Uint64(arg[16:24])
out[3] = binary.LittleEndian.Uint64(arg[24:])
}
// ToBytes converts a field element to a little endian byte array
func (f bls12381FqArithmetic) ToBytes(out *[native.FieldBytes]byte, arg *[native.FieldLimbs]uint64) {
binary.LittleEndian.PutUint64(out[:8], arg[0])
binary.LittleEndian.PutUint64(out[8:16], arg[1])
binary.LittleEndian.PutUint64(out[16:24], arg[2])
binary.LittleEndian.PutUint64(out[24:], arg[3])
}
// Selectznz performs conditional select.
// selects arg1 if choice == 0 and arg2 if choice == 1
func (f bls12381FqArithmetic) Selectznz(out, arg1, arg2 *[native.FieldLimbs]uint64, choice int) {
b := uint64(-choice)
out[0] = arg1[0] ^ ((arg1[0] ^ arg2[0]) & b)
out[1] = arg1[1] ^ ((arg1[1] ^ arg2[1]) & b)
out[2] = arg1[2] ^ ((arg1[2] ^ arg2[2]) & b)
out[3] = arg1[3] ^ ((arg1[3] ^ arg2[3]) & b)
}
func (f bls12381FqArithmetic) montReduce(out *[native.FieldLimbs]uint64, r *[2 * native.FieldLimbs]uint64) {
// Taken from Algorithm 14.32 in Handbook of Applied Cryptography
var r1, r2, r3, r4, r5, r6, carry, carry2, k uint64
var rr [native.FieldLimbs]uint64
k = r[0] * qInv
_, carry = mac(r[0], k, fqModulus[0], 0)
r1, carry = mac(r[1], k, fqModulus[1], carry)
r2, carry = mac(r[2], k, fqModulus[2], carry)
r3, carry = mac(r[3], k, fqModulus[3], carry)
r4, carry2 = adc(r[4], 0, carry)
k = r1 * qInv
_, carry = mac(r1, k, fqModulus[0], 0)
r2, carry = mac(r2, k, fqModulus[1], carry)
r3, carry = mac(r3, k, fqModulus[2], carry)
r4, carry = mac(r4, k, fqModulus[3], carry)
r5, carry2 = adc(r[5], carry2, carry)
k = r2 * qInv
_, carry = mac(r2, k, fqModulus[0], 0)
r3, carry = mac(r3, k, fqModulus[1], carry)
r4, carry = mac(r4, k, fqModulus[2], carry)
r5, carry = mac(r5, k, fqModulus[3], carry)
r6, carry2 = adc(r[6], carry2, carry)
k = r3 * qInv
_, carry = mac(r3, k, fqModulus[0], 0)
rr[0], carry = mac(r4, k, fqModulus[1], carry)
rr[1], carry = mac(r5, k, fqModulus[2], carry)
rr[2], carry = mac(r6, k, fqModulus[3], carry)
rr[3], _ = adc(r[7], carry2, carry)
f.Sub(out, &rr, &fqModulus)
}