mirror of
https://github.com/onsonr/sonr.git
synced 2025-03-11 13:29:12 +00:00
- **refactor: remove unused auth components** - **refactor: improve devbox configuration and deployment process** - **refactor: improve devnet and testnet setup** - **fix: update templ version to v0.2.778** - **refactor: rename pkl/net.matrix to pkl/matrix.net** - **refactor: migrate webapp components to nebula** - **refactor: protobuf types** - **chore: update dependencies for improved security and stability** - **feat: implement landing page and vault gateway servers** - **refactor: Migrate data models to new module structure and update related files** - **feature/1121-implement-ucan-validation** - **refactor: Replace hardcoded constants with model types in attns.go** - **feature/1121-implement-ucan-validation** - **chore: add origin Host struct and update main function to handle multiple hosts** - **build: remove unused static files from dwn module** - **build: remove unused static files from dwn module** - **refactor: Move DWN models to common package** - **refactor: move models to pkg/common** - **refactor: move vault web app assets to embed module** - **refactor: update session middleware import path** - **chore: configure port labels and auto-forwarding behavior** - **feat: enhance devcontainer configuration** - **feat: Add UCAN middleware for Echo with flexible token validation** - **feat: add JWT middleware for UCAN authentication** - **refactor: update package URI and versioning in PklProject files** - **fix: correct sonr.pkl import path** - **refactor: move JWT related code to auth package** - **feat: introduce vault configuration retrieval and management** - **refactor: Move vault components to gateway module and update file paths** - **refactor: remove Dexie and SQLite database implementations** - **feat: enhance frontend with PWA features and WASM integration** - **feat: add Devbox features and streamline Dockerfile** - **chore: update dependencies to include TigerBeetle** - **chore(deps): update go version to 1.23** - **feat: enhance devnet setup with PATH environment variable and updated PWA manifest** - **fix: upgrade tigerbeetle-go dependency and remove indirect dependency** - **feat: add PostgreSQL support to devnet and testnet deployments** - **refactor: rename keyshare cookie to token cookie** - **feat: upgrade Go version to 1.23.3 and update dependencies** - **refactor: update devnet and testnet configurations** - **feat: add IPFS configuration for devnet** - **I'll help you update the ipfs.config.pkl to include all the peers from the shell script. Here's the updated configuration:** - **refactor: move mpc package to crypto directory** - **feat: add BIP32 support for various cryptocurrencies** - **feat: enhance ATN.pkl with additional capabilities** - **refactor: simplify smart account and vault attenuation creation** - **feat: add new capabilities to the Attenuation type** - **refactor: Rename MPC files for clarity and consistency** - **feat: add DIDKey support for cryptographic operations** - **feat: add devnet and testnet deployment configurations** - **fix: correct key derivation in bip32 package** - **refactor: rename crypto/bip32 package to crypto/accaddr** - **fix: remove duplicate indirect dependency** - **refactor: move vault package to root directory** - **refactor: update routes for gateway and vault** - **refactor: remove obsolete web configuration file** - **refactor: remove unused TigerBeetle imports and update host configuration** - **refactor: adjust styles directory path** - **feat: add broadcastTx and simulateTx functions to gateway** - **feat: add PinVault handler**
469 lines
12 KiB
Go
Executable File
469 lines
12 KiB
Go
Executable File
package native
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"crypto/sha512"
|
|
"fmt"
|
|
"hash"
|
|
"io"
|
|
"math/big"
|
|
|
|
"github.com/pkg/errors"
|
|
"golang.org/x/crypto/blake2b"
|
|
"golang.org/x/crypto/sha3"
|
|
)
|
|
|
|
// EllipticPointHashType is to indicate which expand operation is used
|
|
// for hash to curve operations
|
|
type EllipticPointHashType uint
|
|
|
|
// EllipticPointHashName is to indicate the hash function is used
|
|
// for hash to curve operations
|
|
type EllipticPointHashName uint
|
|
|
|
const (
|
|
// XMD - use ExpandMsgXmd
|
|
XMD EllipticPointHashType = iota
|
|
// XOF - use ExpandMsgXof
|
|
XOF
|
|
)
|
|
|
|
const (
|
|
SHA256 EllipticPointHashName = iota
|
|
SHA512
|
|
SHA3_256
|
|
SHA3_384
|
|
SHA3_512
|
|
BLAKE2B
|
|
SHAKE128
|
|
SHAKE256
|
|
)
|
|
|
|
// EllipticPoint represents a Weierstrauss elliptic curve point
|
|
type EllipticPoint struct {
|
|
X *Field
|
|
Y *Field
|
|
Z *Field
|
|
Params *EllipticPointParams
|
|
Arithmetic EllipticPointArithmetic
|
|
}
|
|
|
|
// EllipticPointParams are the Weierstrauss curve parameters
|
|
// such as the name, the coefficients the generator point,
|
|
// and the prime bit size
|
|
type EllipticPointParams struct {
|
|
Name string
|
|
A *Field
|
|
B *Field
|
|
Gx *Field
|
|
Gy *Field
|
|
BitSize int
|
|
}
|
|
|
|
// EllipticPointHasher is the type of hashing methods for
|
|
// hashing byte sequences to curve point.
|
|
type EllipticPointHasher struct {
|
|
name EllipticPointHashName
|
|
hashType EllipticPointHashType
|
|
xmd hash.Hash
|
|
xof sha3.ShakeHash
|
|
}
|
|
|
|
// Name returns the hash name for this hasher
|
|
func (e *EllipticPointHasher) Name() string {
|
|
return e.name.String()
|
|
}
|
|
|
|
// Type returns the hash type for this hasher
|
|
func (e *EllipticPointHasher) Type() EllipticPointHashType {
|
|
return e.hashType
|
|
}
|
|
|
|
// Xmd returns the hash method for ExpandMsgXmd
|
|
func (e *EllipticPointHasher) Xmd() hash.Hash {
|
|
return e.xmd
|
|
}
|
|
|
|
// Xof returns the hash method for ExpandMsgXof
|
|
func (e *EllipticPointHasher) Xof() sha3.ShakeHash {
|
|
return e.xof
|
|
}
|
|
|
|
// EllipticPointHasherSha256 creates a point hasher that uses Sha256
|
|
func EllipticPointHasherSha256() *EllipticPointHasher {
|
|
return &EllipticPointHasher{
|
|
name: SHA256,
|
|
hashType: XMD,
|
|
xmd: sha256.New(),
|
|
}
|
|
}
|
|
|
|
// EllipticPointHasherSha512 creates a point hasher that uses Sha512
|
|
func EllipticPointHasherSha512() *EllipticPointHasher {
|
|
return &EllipticPointHasher{
|
|
name: SHA512,
|
|
hashType: XMD,
|
|
xmd: sha512.New(),
|
|
}
|
|
}
|
|
|
|
// EllipticPointHasherSha3256 creates a point hasher that uses Sha3256
|
|
func EllipticPointHasherSha3256() *EllipticPointHasher {
|
|
return &EllipticPointHasher{
|
|
name: SHA3_256,
|
|
hashType: XMD,
|
|
xmd: sha3.New256(),
|
|
}
|
|
}
|
|
|
|
// EllipticPointHasherSha3384 creates a point hasher that uses Sha3384
|
|
func EllipticPointHasherSha3384() *EllipticPointHasher {
|
|
return &EllipticPointHasher{
|
|
name: SHA3_384,
|
|
hashType: XMD,
|
|
xmd: sha3.New384(),
|
|
}
|
|
}
|
|
|
|
// EllipticPointHasherSha3512 creates a point hasher that uses Sha3512
|
|
func EllipticPointHasherSha3512() *EllipticPointHasher {
|
|
return &EllipticPointHasher{
|
|
name: SHA3_512,
|
|
hashType: XMD,
|
|
xmd: sha3.New512(),
|
|
}
|
|
}
|
|
|
|
// EllipticPointHasherBlake2b creates a point hasher that uses Blake2b
|
|
func EllipticPointHasherBlake2b() *EllipticPointHasher {
|
|
h, _ := blake2b.New(64, []byte{})
|
|
return &EllipticPointHasher{
|
|
name: BLAKE2B,
|
|
hashType: XMD,
|
|
xmd: h,
|
|
}
|
|
}
|
|
|
|
// EllipticPointHasherShake128 creates a point hasher that uses Shake128
|
|
func EllipticPointHasherShake128() *EllipticPointHasher {
|
|
return &EllipticPointHasher{
|
|
name: SHAKE128,
|
|
hashType: XOF,
|
|
xof: sha3.NewShake128(),
|
|
}
|
|
}
|
|
|
|
// EllipticPointHasherShake256 creates a point hasher that uses Shake256
|
|
func EllipticPointHasherShake256() *EllipticPointHasher {
|
|
return &EllipticPointHasher{
|
|
name: SHAKE128,
|
|
hashType: XOF,
|
|
xof: sha3.NewShake256(),
|
|
}
|
|
}
|
|
|
|
// EllipticPointArithmetic are the methods that specific curves
|
|
// need to implement for higher abstractions to wrap the point
|
|
type EllipticPointArithmetic interface {
|
|
// Hash a byte sequence to the curve using the specified hasher
|
|
// and dst and store the result in out
|
|
Hash(out *EllipticPoint, hasher *EllipticPointHasher, bytes, dst []byte) error
|
|
// Double arg and store the result in out
|
|
Double(out, arg *EllipticPoint)
|
|
// Add arg1 with arg2 and store the result in out
|
|
Add(out, arg1, arg2 *EllipticPoint)
|
|
// IsOnCurve tests arg if it represents a valid point on the curve
|
|
IsOnCurve(arg *EllipticPoint) bool
|
|
// ToAffine converts arg to affine coordinates storing the result in out
|
|
ToAffine(out, arg *EllipticPoint)
|
|
// RhsEq computes the right-hand side of the ecc equation
|
|
RhsEq(out, x *Field)
|
|
}
|
|
|
|
func (t EllipticPointHashType) String() string {
|
|
switch t {
|
|
case XMD:
|
|
return "XMD"
|
|
case XOF:
|
|
return "XOF"
|
|
}
|
|
return "unknown"
|
|
}
|
|
|
|
func (n EllipticPointHashName) String() string {
|
|
switch n {
|
|
case SHA256:
|
|
return "SHA-256"
|
|
case SHA512:
|
|
return "SHA-512"
|
|
case SHA3_256:
|
|
return "SHA3-256"
|
|
case SHA3_384:
|
|
return "SHA3-384"
|
|
case SHA3_512:
|
|
return "SHA3-512"
|
|
case BLAKE2B:
|
|
return "BLAKE2b"
|
|
case SHAKE128:
|
|
return "SHAKE-128"
|
|
case SHAKE256:
|
|
return "SHAKE-256"
|
|
}
|
|
return "unknown"
|
|
}
|
|
|
|
// Random creates a random point on the curve
|
|
// from the specified reader
|
|
func (p *EllipticPoint) Random(reader io.Reader) (*EllipticPoint, error) {
|
|
var seed [WideFieldBytes]byte
|
|
n, err := reader.Read(seed[:])
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "random could not read from stream")
|
|
}
|
|
if n != WideFieldBytes {
|
|
return nil, fmt.Errorf("insufficient bytes read %d when %d are needed", n, WideFieldBytes)
|
|
}
|
|
dst := []byte(fmt.Sprintf("%s_XMD:SHA-256_SSWU_RO_", p.Params.Name))
|
|
err = p.Arithmetic.Hash(p, EllipticPointHasherSha256(), seed[:], dst)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "ecc hash failed")
|
|
}
|
|
return p, nil
|
|
}
|
|
|
|
// Hash uses the hasher to map bytes to a valid point
|
|
func (p *EllipticPoint) Hash(bytes []byte, hasher *EllipticPointHasher) (*EllipticPoint, error) {
|
|
dst := []byte(fmt.Sprintf("%s_%s:%s_SSWU_RO_", p.Params.Name, hasher.hashType, hasher.name))
|
|
err := p.Arithmetic.Hash(p, hasher, bytes, dst)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "hash failed")
|
|
}
|
|
return p, nil
|
|
}
|
|
|
|
// Identity returns the identity point
|
|
func (p *EllipticPoint) Identity() *EllipticPoint {
|
|
p.X.SetZero()
|
|
p.Y.SetZero()
|
|
p.Z.SetZero()
|
|
return p
|
|
}
|
|
|
|
// Generator returns the base point for the curve
|
|
func (p *EllipticPoint) Generator() *EllipticPoint {
|
|
p.X.Set(p.Params.Gx)
|
|
p.Y.Set(p.Params.Gy)
|
|
p.Z.SetOne()
|
|
return p
|
|
}
|
|
|
|
// IsIdentity returns true if this point is at infinity
|
|
func (p *EllipticPoint) IsIdentity() bool {
|
|
return p.Z.IsZero() == 1
|
|
}
|
|
|
|
// Double this point
|
|
func (p *EllipticPoint) Double(point *EllipticPoint) *EllipticPoint {
|
|
p.Set(point)
|
|
p.Arithmetic.Double(p, point)
|
|
return p
|
|
}
|
|
|
|
// Neg negates this point
|
|
func (p *EllipticPoint) Neg(point *EllipticPoint) *EllipticPoint {
|
|
p.Set(point)
|
|
p.Y.Neg(p.Y)
|
|
return p
|
|
}
|
|
|
|
// Add adds the two points
|
|
func (p *EllipticPoint) Add(lhs, rhs *EllipticPoint) *EllipticPoint {
|
|
p.Set(lhs)
|
|
p.Arithmetic.Add(p, lhs, rhs)
|
|
return p
|
|
}
|
|
|
|
// Sub subtracts the two points
|
|
func (p *EllipticPoint) Sub(lhs, rhs *EllipticPoint) *EllipticPoint {
|
|
p.Set(lhs)
|
|
p.Arithmetic.Add(p, lhs, new(EllipticPoint).Neg(rhs))
|
|
return p
|
|
}
|
|
|
|
// Mul multiplies this point by the input scalar
|
|
func (p *EllipticPoint) Mul(point *EllipticPoint, scalar *Field) *EllipticPoint {
|
|
bytes := scalar.Bytes()
|
|
precomputed := [16]*EllipticPoint{}
|
|
precomputed[0] = new(EllipticPoint).Set(point).Identity()
|
|
precomputed[1] = new(EllipticPoint).Set(point)
|
|
for i := 2; i < 16; i += 2 {
|
|
precomputed[i] = new(EllipticPoint).Set(point).Double(precomputed[i>>1])
|
|
precomputed[i+1] = new(EllipticPoint).Set(point).Add(precomputed[i], point)
|
|
}
|
|
p.Identity()
|
|
for i := 0; i < 256; i += 4 {
|
|
// Brouwer / windowing method. window size of 4.
|
|
for j := 0; j < 4; j++ {
|
|
p.Double(p)
|
|
}
|
|
window := bytes[32-1-i>>3] >> (4 - i&0x04) & 0x0F
|
|
p.Add(p, precomputed[window])
|
|
}
|
|
return p
|
|
}
|
|
|
|
// Equal returns 1 if the two points are equal 0 otherwise.
|
|
func (p *EllipticPoint) Equal(rhs *EllipticPoint) int {
|
|
var x1, x2, y1, y2 Field
|
|
|
|
x1.Arithmetic = p.X.Arithmetic
|
|
x2.Arithmetic = p.X.Arithmetic
|
|
y1.Arithmetic = p.Y.Arithmetic
|
|
y2.Arithmetic = p.Y.Arithmetic
|
|
|
|
x1.Mul(p.X, rhs.Z)
|
|
x2.Mul(rhs.X, p.Z)
|
|
|
|
y1.Mul(p.Y, rhs.Z)
|
|
y2.Mul(rhs.Y, p.Z)
|
|
|
|
e1 := p.Z.IsZero()
|
|
e2 := rhs.Z.IsZero()
|
|
|
|
// Both at infinity or coordinates are the same
|
|
return (e1 & e2) | (^e1 & ^e2)&x1.Equal(&x2)&y1.Equal(&y2)
|
|
}
|
|
|
|
// Set copies clone into p
|
|
func (p *EllipticPoint) Set(clone *EllipticPoint) *EllipticPoint {
|
|
p.X = new(Field).Set(clone.X)
|
|
p.Y = new(Field).Set(clone.Y)
|
|
p.Z = new(Field).Set(clone.Z)
|
|
p.Params = clone.Params
|
|
p.Arithmetic = clone.Arithmetic
|
|
return p
|
|
}
|
|
|
|
// BigInt returns the x and y as big.Ints in affine
|
|
func (p *EllipticPoint) BigInt() (x, y *big.Int) {
|
|
t := new(EllipticPoint).Set(p)
|
|
p.Arithmetic.ToAffine(t, p)
|
|
x = t.X.BigInt()
|
|
y = t.Y.BigInt()
|
|
return
|
|
}
|
|
|
|
// SetBigInt creates a point from affine x, y
|
|
// and returns the point if it is on the curve
|
|
func (p *EllipticPoint) SetBigInt(x, y *big.Int) (*EllipticPoint, error) {
|
|
xx := &Field{
|
|
Params: p.Params.Gx.Params,
|
|
Arithmetic: p.Params.Gx.Arithmetic,
|
|
}
|
|
xx.SetBigInt(x)
|
|
yy := &Field{
|
|
Params: p.Params.Gx.Params,
|
|
Arithmetic: p.Params.Gx.Arithmetic,
|
|
}
|
|
yy.SetBigInt(y)
|
|
pp := new(EllipticPoint).Set(p)
|
|
|
|
zero := new(Field).Set(xx).SetZero()
|
|
one := new(Field).Set(xx).SetOne()
|
|
isIdentity := xx.IsZero() & yy.IsZero()
|
|
pp.X = xx.CMove(xx, zero, isIdentity)
|
|
pp.Y = yy.CMove(yy, zero, isIdentity)
|
|
pp.Z = one.CMove(one, zero, isIdentity)
|
|
if !p.Arithmetic.IsOnCurve(pp) && isIdentity == 0 {
|
|
return nil, fmt.Errorf("invalid coordinates")
|
|
}
|
|
return p.Set(pp), nil
|
|
}
|
|
|
|
// GetX returns the affine X coordinate
|
|
func (p *EllipticPoint) GetX() *Field {
|
|
t := new(EllipticPoint).Set(p)
|
|
p.Arithmetic.ToAffine(t, p)
|
|
return t.X
|
|
}
|
|
|
|
// GetY returns the affine Y coordinate
|
|
func (p *EllipticPoint) GetY() *Field {
|
|
t := new(EllipticPoint).Set(p)
|
|
p.Arithmetic.ToAffine(t, p)
|
|
return t.Y
|
|
}
|
|
|
|
// IsOnCurve determines if this point represents a valid curve point
|
|
func (p *EllipticPoint) IsOnCurve() bool {
|
|
return p.Arithmetic.IsOnCurve(p)
|
|
}
|
|
|
|
// ToAffine converts the point into affine coordinates
|
|
func (p *EllipticPoint) ToAffine(clone *EllipticPoint) *EllipticPoint {
|
|
p.Arithmetic.ToAffine(p, clone)
|
|
return p
|
|
}
|
|
|
|
// SumOfProducts computes the multi-exponentiation for the specified
|
|
// points and scalars and stores the result in `p`.
|
|
// Returns an error if the lengths of the arguments is not equal.
|
|
func (p *EllipticPoint) SumOfProducts(points []*EllipticPoint, scalars []*Field) (*EllipticPoint, error) {
|
|
const Upper = 256
|
|
const W = 4
|
|
const Windows = Upper / W // careful--use ceiling division in case this doesn't divide evenly
|
|
if len(points) != len(scalars) {
|
|
return nil, fmt.Errorf("length mismatch")
|
|
}
|
|
|
|
bucketSize := 1 << W
|
|
windows := make([]*EllipticPoint, Windows)
|
|
bytes := make([][32]byte, len(scalars))
|
|
buckets := make([]*EllipticPoint, bucketSize)
|
|
|
|
for i, scalar := range scalars {
|
|
bytes[i] = scalar.Bytes()
|
|
}
|
|
for i := range windows {
|
|
windows[i] = new(EllipticPoint).Set(p).Identity()
|
|
}
|
|
|
|
for i := 0; i < bucketSize; i++ {
|
|
buckets[i] = new(EllipticPoint).Set(p).Identity()
|
|
}
|
|
|
|
sum := new(EllipticPoint).Set(p)
|
|
|
|
for j := 0; j < len(windows); j++ {
|
|
for i := 0; i < bucketSize; i++ {
|
|
buckets[i].Identity()
|
|
}
|
|
|
|
for i := 0; i < len(scalars); i++ {
|
|
// j*W to get the nibble
|
|
// >> 3 to convert to byte, / 8
|
|
// (W * j & W) gets the nibble, mod W
|
|
// 1 << W - 1 to get the offset
|
|
index := bytes[i][j*W>>3] >> (W * j & W) & (1<<W - 1) // little-endian
|
|
buckets[index].Add(buckets[index], points[i])
|
|
}
|
|
|
|
sum.Identity()
|
|
|
|
for i := bucketSize - 1; i > 0; i-- {
|
|
sum.Add(sum, buckets[i])
|
|
windows[j].Add(windows[j], sum)
|
|
}
|
|
}
|
|
|
|
p.Identity()
|
|
for i := len(windows) - 1; i >= 0; i-- {
|
|
for j := 0; j < W; j++ {
|
|
p.Double(p)
|
|
}
|
|
|
|
p.Add(p, windows[i])
|
|
}
|
|
return p, nil
|
|
}
|