209 lines
5.6 KiB
Go
Raw Permalink Normal View History

feature/1114 implement account interface (#1167) - **refactor: move session-related code to middleware package** - **refactor: update PKL build process and adjust related configurations** - **feat: integrate base.cosmos.v1 Genesis module** - **refactor: pass session context to modal rendering functions** - **refactor: move nebula package to app directory and update templ version** - **refactor: Move home section video view to dedicated directory** - **refactor: remove unused views file** - **refactor: move styles and UI components to global scope** - **refactor: Rename images.go to cdn.go** - **feat: Add Empty State Illustrations** - **refactor: Consolidate Vault Index Logic** - **fix: References to App.wasm and remove Vault Directory embedded CDN files** - **refactor: Move CDN types to Models** - **fix: Correct line numbers in templ error messages for arch_templ.go** - **refactor: use common types for peer roles** - **refactor: move common types and ORM to a shared package** - **fix: Config import dwn** - **refactor: move nebula directory to app** - **feat: Rebuild nebula** - **fix: correct file paths in panels templates** - **feat: Remove duplicate types** - **refactor: Move dwn to pkg/core** - **refactor: Binary Structure** - **feat: Introduce Crypto Pkg** - **fix: Broken Process Start** - **feat: Update pkg/* structure** - **feat: Refactor PKL Structure** - **build: update pkl build process** - **chore: Remove Empty Files** - **refactor: remove unused macaroon package** - **feat: Add WebAwesome Components** - **refactor: consolidate build and generation tasks into a single taskfile, remove redundant makefile targets** - **refactor: refactor server and move components to pkg/core/dwn** - **build: update go modules** - **refactor: move gateway logic into dedicated hway command** - **feat: Add KSS (Krawczyk-Song-Song) MPC cryptography module** - **feat: Implement MPC-based JWT signing and UCAN token generation** - **feat: add support for MPC-based JWT signing** - **feat: Implement MPC-based UCAN capabilities for smart accounts** - **feat: add address field to keyshareSource** - **feat: Add comprehensive MPC test suite for keyshares, UCAN tokens, and token attenuations** - **refactor: improve MPC keyshare management and signing process** - **feat: enhance MPC capability hierarchy documentation** - **refactor: rename GenerateKeyshares function to NewKeyshareSource for clarity** - **refactor: remove unused Ethereum address computation** - **feat: Add HasHandle and IsAuthenticated methods to HTTPContext** - **refactor: Add context.Context support to session HTTPContext** - **refactor: Resolve context interface conflicts in HTTPContext** - **feat: Add session ID context key and helper functions** - **feat: Update WebApp Page Rendering** - **refactor: Simplify context management by using single HTTPContext key** - **refactor: Simplify HTTPContext creation and context management in session middleware** - **refactor: refactor session middleware to use a single data structure** - **refactor: Simplify HTTPContext implementation and session data handling** - **refactor: Improve session context handling and prevent nil pointer errors** - **refactor: Improve session context handling with nil safety and type support** - **refactor: improve session data injection** - **feat: add full-screen modal component and update registration flow** - **chore: add .air.toml to .gitignore** - **feat: add Air to devbox and update dependencies**
2024-11-23 01:28:58 -05:00
//
// Copyright Coinbase, Inc. All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//
// Package bls_sig is an implementation of the BLS signature defined in https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03
package bls_sig
import (
"crypto/rand"
"crypto/sha256"
"crypto/subtle"
"fmt"
"golang.org/x/crypto/hkdf"
"github.com/onsonr/sonr/crypto/core/curves"
"github.com/onsonr/sonr/crypto/core/curves/native"
"github.com/onsonr/sonr/crypto/core/curves/native/bls12381"
"github.com/onsonr/sonr/crypto/internal"
"github.com/onsonr/sonr/crypto/sharing"
feature/1114 implement account interface (#1167) - **refactor: move session-related code to middleware package** - **refactor: update PKL build process and adjust related configurations** - **feat: integrate base.cosmos.v1 Genesis module** - **refactor: pass session context to modal rendering functions** - **refactor: move nebula package to app directory and update templ version** - **refactor: Move home section video view to dedicated directory** - **refactor: remove unused views file** - **refactor: move styles and UI components to global scope** - **refactor: Rename images.go to cdn.go** - **feat: Add Empty State Illustrations** - **refactor: Consolidate Vault Index Logic** - **fix: References to App.wasm and remove Vault Directory embedded CDN files** - **refactor: Move CDN types to Models** - **fix: Correct line numbers in templ error messages for arch_templ.go** - **refactor: use common types for peer roles** - **refactor: move common types and ORM to a shared package** - **fix: Config import dwn** - **refactor: move nebula directory to app** - **feat: Rebuild nebula** - **fix: correct file paths in panels templates** - **feat: Remove duplicate types** - **refactor: Move dwn to pkg/core** - **refactor: Binary Structure** - **feat: Introduce Crypto Pkg** - **fix: Broken Process Start** - **feat: Update pkg/* structure** - **feat: Refactor PKL Structure** - **build: update pkl build process** - **chore: Remove Empty Files** - **refactor: remove unused macaroon package** - **feat: Add WebAwesome Components** - **refactor: consolidate build and generation tasks into a single taskfile, remove redundant makefile targets** - **refactor: refactor server and move components to pkg/core/dwn** - **build: update go modules** - **refactor: move gateway logic into dedicated hway command** - **feat: Add KSS (Krawczyk-Song-Song) MPC cryptography module** - **feat: Implement MPC-based JWT signing and UCAN token generation** - **feat: add support for MPC-based JWT signing** - **feat: Implement MPC-based UCAN capabilities for smart accounts** - **feat: add address field to keyshareSource** - **feat: Add comprehensive MPC test suite for keyshares, UCAN tokens, and token attenuations** - **refactor: improve MPC keyshare management and signing process** - **feat: enhance MPC capability hierarchy documentation** - **refactor: rename GenerateKeyshares function to NewKeyshareSource for clarity** - **refactor: remove unused Ethereum address computation** - **feat: Add HasHandle and IsAuthenticated methods to HTTPContext** - **refactor: Add context.Context support to session HTTPContext** - **refactor: Resolve context interface conflicts in HTTPContext** - **feat: Add session ID context key and helper functions** - **feat: Update WebApp Page Rendering** - **refactor: Simplify context management by using single HTTPContext key** - **refactor: Simplify HTTPContext creation and context management in session middleware** - **refactor: refactor session middleware to use a single data structure** - **refactor: Simplify HTTPContext implementation and session data handling** - **refactor: Improve session context handling and prevent nil pointer errors** - **refactor: Improve session context handling with nil safety and type support** - **refactor: improve session data injection** - **feat: add full-screen modal component and update registration flow** - **chore: add .air.toml to .gitignore** - **feat: add Air to devbox and update dependencies**
2024-11-23 01:28:58 -05:00
)
// Secret key in Fr
const SecretKeySize = 32
// Secret key share with identifier byte in Fr
const SecretKeyShareSize = 33
// The salt used with generating secret keys
// See section 2.3 from https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03
const hkdfKeyGenSalt = "BLS-SIG-KEYGEN-SALT-"
// Represents a value mod r where r is the curve order or
// order of the subgroups in G1 and G2
type SecretKey struct {
value *native.Field
}
func allRowsUnique(data [][]byte) bool {
seen := make(map[string]bool)
for _, row := range data {
m := string(row)
if _, ok := seen[m]; ok {
return false
}
seen[m] = true
}
return true
}
func generateRandBytes(count int) ([]byte, error) {
ikm := make([]byte, count)
cnt, err := rand.Read(ikm)
if err != nil {
return nil, err
}
if cnt != count {
return nil, fmt.Errorf("unable to read sufficient random data")
}
return ikm, nil
}
// Creates a new BLS secret key
// Input key material (ikm) MUST be at least 32 bytes long,
// but it MAY be longer.
func (sk SecretKey) Generate(ikm []byte) (*SecretKey, error) {
if len(ikm) < 32 {
return nil, fmt.Errorf("ikm is too short. Must be at least 32")
}
// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04#section-2.3
h := sha256.New()
n, err := h.Write([]byte(hkdfKeyGenSalt))
if err != nil {
return nil, err
}
if n != len(hkdfKeyGenSalt) {
return nil, fmt.Errorf("incorrect salt bytes written to be hashed")
}
salt := h.Sum(nil)
ikm = append(ikm, 0)
// Leaves key_info parameter as the default empty string
// and just adds parameter I2OSP(L, 2)
var okm [native.WideFieldBytes]byte
kdf := hkdf.New(sha256.New, ikm, salt, []byte{0, 48})
read, err := kdf.Read(okm[:48])
copy(okm[:48], internal.ReverseScalarBytes(okm[:48]))
if err != nil {
return nil, err
}
if read != 48 {
return nil, fmt.Errorf("failed to create private key")
}
v := bls12381.Bls12381FqNew().SetBytesWide(&okm)
return &SecretKey{value: v}, nil
}
// Serialize a secret key to raw bytes
func (sk SecretKey) MarshalBinary() ([]byte, error) {
bytes := sk.value.Bytes()
return internal.ReverseScalarBytes(bytes[:]), nil
}
// Deserialize a secret key from raw bytes
// Cannot be zero. Must be 32 bytes and cannot be all zeroes.
// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-03#section-2.3
func (sk *SecretKey) UnmarshalBinary(data []byte) error {
if len(data) != SecretKeySize {
return fmt.Errorf("secret key must be %d bytes", SecretKeySize)
}
zeros := make([]byte, len(data))
if subtle.ConstantTimeCompare(data, zeros) == 1 {
return fmt.Errorf("secret key cannot be zero")
}
var bb [native.FieldBytes]byte
copy(bb[:], internal.ReverseScalarBytes(data))
value, err := bls12381.Bls12381FqNew().SetBytes(&bb)
if err != nil {
return err
}
sk.value = value
return nil
}
// SecretKeyShare is shamir share of a private key
type SecretKeyShare struct {
identifier byte
value []byte
}
// Serialize a secret key share to raw bytes
func (sks SecretKeyShare) MarshalBinary() ([]byte, error) {
var blob [SecretKeyShareSize]byte
l := len(sks.value)
copy(blob[:l], sks.value)
blob[l] = sks.identifier
return blob[:], nil
}
// Deserialize a secret key share from raw bytes
func (sks *SecretKeyShare) UnmarshalBinary(data []byte) error {
if len(data) != SecretKeyShareSize {
return fmt.Errorf("secret key share must be %d bytes", SecretKeyShareSize)
}
zeros := make([]byte, len(data))
if subtle.ConstantTimeCompare(data, zeros) == 1 {
return fmt.Errorf("secret key share cannot be zero")
}
l := len(data)
sks.identifier = data[l-1]
sks.value = make([]byte, SecretKeySize)
copy(sks.value, data[:l])
return nil
}
// thresholdizeSecretKey splits a composite secret key such that
// `threshold` partial signatures can be combined to form a composite signature
func thresholdizeSecretKey(secretKey *SecretKey, threshold, total uint) ([]*SecretKeyShare, error) {
// Verify our parameters are acceptable.
if secretKey == nil {
return nil, fmt.Errorf("secret key is nil")
}
if threshold > total {
return nil, fmt.Errorf("threshold cannot be greater than the total")
}
if threshold == 0 {
return nil, fmt.Errorf("threshold cannot be zero")
}
if total <= 1 {
return nil, fmt.Errorf("total must be larger than 1")
}
if total > 255 || threshold > 255 {
return nil, fmt.Errorf("cannot have more than 255 shares")
}
curve := curves.BLS12381G1()
sss, err := sharing.NewShamir(uint32(threshold), uint32(total), curve)
if err != nil {
return nil, err
}
secret, ok := curve.NewScalar().(*curves.ScalarBls12381)
if !ok {
return nil, fmt.Errorf("invalid curve")
}
secret.Value = secretKey.value
shares, err := sss.Split(secret, rand.Reader)
if err != nil {
return nil, err
}
// Verify we got the expected number of shares
if uint(len(shares)) != total {
return nil, fmt.Errorf("%v != %v shares", len(shares), total)
}
// Package our shares
secrets := make([]*SecretKeyShare, len(shares))
for i, s := range shares {
// users expect BigEndian
sks := &SecretKeyShare{identifier: byte(s.Id), value: s.Value}
secrets[i] = sks
}
return secrets, nil
}