ceremonyclient/node/keys/inmem.go
Cassandra Heart dbd95bd9e9
v2.1.0 (#439)
* v2.1.0 [omit consensus and adjacent] - this commit will be amended with the full release after the file copy is complete

* 2.1.0 main node rollup
2025-09-30 02:48:15 -05:00

329 lines
7.6 KiB
Go

package keys
import (
"bytes"
"crypto/ed25519"
"crypto/sha256"
"slices"
"github.com/btcsuite/btcd/btcec"
"github.com/cloudflare/circl/sign/ed448"
"github.com/pkg/errors"
"golang.org/x/crypto/sha3"
qcrypto "source.quilibrium.com/quilibrium/monorepo/types/crypto"
"source.quilibrium.com/quilibrium/monorepo/types/keys"
)
type InMemoryKeyManager struct {
key keys.ByteString
store map[string]keys.Key
blsKeyConstructor qcrypto.BlsConstructor
decafConstructor qcrypto.DecafConstructor
}
// ValidateSignature implements KeyManager.
func (f *InMemoryKeyManager) ValidateSignature(
keyType qcrypto.KeyType,
publicKey []byte,
message []byte,
signature []byte,
domain []byte,
) (bool, error) {
switch keyType {
case qcrypto.KeyTypeEd448:
return ed448.Verify(
ed448.PublicKey(publicKey),
slices.Concat(domain, message),
signature,
"",
), nil
case qcrypto.KeyTypeBLS48581G1:
fallthrough
case qcrypto.KeyTypeBLS48581G2:
return f.blsKeyConstructor.VerifySignatureRaw(
publicKey,
signature,
message,
domain,
), nil
case qcrypto.KeyTypeSecp256K1SHA256:
digest := sha256.Sum256(slices.Concat(domain, message))
pubkey, _, err := btcec.RecoverCompact(btcec.S256(), signature, digest[:])
if err != nil {
return false, errors.Wrap(err, "validate signature")
}
return bytes.Equal(publicKey, pubkey.SerializeCompressed()), nil
case qcrypto.KeyTypeSecp256K1SHA3:
digest := sha3.Sum256(slices.Concat(domain, message))
pubkey, _, err := btcec.RecoverCompact(btcec.S256(), signature, digest[:])
if err != nil {
return false, errors.Wrap(err, "validate signature")
}
return bytes.Equal(publicKey, pubkey.SerializeCompressed()), nil
case qcrypto.KeyTypeEd25519:
return ed25519.Verify(
ed25519.PublicKey(publicKey),
slices.Concat(domain, message),
signature,
), nil
}
return false, nil
}
func NewInMemoryKeyManager(
blsKeyConstructor qcrypto.BlsConstructor,
decafConstructor qcrypto.DecafConstructor,
) *InMemoryKeyManager {
store := make(map[string]keys.Key)
return &InMemoryKeyManager{
store: store,
blsKeyConstructor: blsKeyConstructor,
decafConstructor: decafConstructor,
}
}
// CreateSigningKey implements KeyManager
func (f *InMemoryKeyManager) CreateSigningKey(
id string,
keyType qcrypto.KeyType,
) (qcrypto.Signer, []byte, error) {
switch keyType {
case qcrypto.KeyTypeEd448:
ed448Key, err := NewEd448Key()
if err != nil {
return nil, nil, errors.Wrap(err, "create signing key")
}
if err = f.save(
id,
keys.Key{
Id: id,
Type: keyType,
PublicKey: keys.ByteString(ed448Key.Public().([]byte)),
PrivateKey: keys.ByteString(ed448Key.Private()),
},
); err != nil {
return nil, nil, errors.Wrap(err, "create signing key")
}
return ed448Key, nil, nil
case qcrypto.KeyTypeBLS48581G1:
fallthrough
case qcrypto.KeyTypeBLS48581G2:
blskey, popk, err := f.blsKeyConstructor.New()
if err != nil {
return nil, nil, errors.Wrap(err, "create signing key")
}
if err = f.save(
id,
keys.Key{
Id: id,
Type: keyType,
PublicKey: keys.ByteString(blskey.Public().([]byte)),
PrivateKey: keys.ByteString(blskey.Private()),
},
); err != nil {
return nil, nil, errors.Wrap(err, "create signing key")
}
return blskey, popk, nil
// case KeyTypePCAS:
// _, privkey, err := addressing.GenerateKey(rand.Reader)
// if err != nil {
// return nil, errors.Wrap(err, "could not generate key")
// }
// if err = f.save(id, privkey); err != nil {
// return nil, errors.Wrap(err, "could not save")
// }
// return privkey, nil
}
return nil, nil, UnsupportedKeyTypeErr
}
// CreateAgreementKey implements KeyManager
func (f *InMemoryKeyManager) CreateAgreementKey(
id string,
keyType qcrypto.KeyType,
) (qcrypto.Agreement, error) {
switch keyType {
case qcrypto.KeyTypeX448:
x448Key := NewX448Key()
if err := f.save(
id,
keys.Key{
Id: id,
Type: qcrypto.KeyTypeX448,
PublicKey: x448Key.Public(),
PrivateKey: x448Key.Private(),
},
); err != nil {
return nil, errors.Wrap(err, "could not save")
}
return x448Key, nil
case qcrypto.KeyTypeDecaf448:
decafKey, err := f.decafConstructor.New()
if err != nil {
return nil, errors.Wrap(err, "create agreement key")
}
if err := f.save(
id,
keys.Key{
Id: id,
Type: qcrypto.KeyTypeDecaf448,
PublicKey: decafKey.Public(),
PrivateKey: decafKey.Private(),
},
); err != nil {
return nil, errors.Wrap(err, "create agreement key")
}
return decafKey, nil
}
return nil, UnsupportedKeyTypeErr
}
// GetAgreementKey implements KeyManager
func (f *InMemoryKeyManager) GetAgreementKey(
id string,
) (qcrypto.Agreement, error) {
key, err := f.read(id)
if err != nil {
return nil, err
}
switch key.Type {
case qcrypto.KeyTypeX448:
x448Key, err := X448KeyFromBytes(key.PrivateKey)
return x448Key, errors.Wrap(err, "get agreement key")
case qcrypto.KeyTypeDecaf448:
decafKey, err := f.decafConstructor.FromBytes(key.PrivateKey, key.PublicKey)
return decafKey, errors.Wrap(err, "get agreement key")
}
return nil, UnsupportedKeyTypeErr
}
// GetRawKey implements KeyManager
func (f *InMemoryKeyManager) GetRawKey(id string) (*keys.Key, error) {
key, err := f.read(id)
return &key, err
}
// GetSigningKey implements KeyManager
func (f *InMemoryKeyManager) GetSigningKey(id string) (qcrypto.Signer, error) {
key, err := f.read(id)
if err != nil {
return nil, err
}
switch key.Type {
case qcrypto.KeyTypeEd448:
ed448Key, err := Ed448KeyFromBytes(key.PrivateKey, key.PublicKey)
return ed448Key, errors.Wrap(err, "get signing key")
case qcrypto.KeyTypeBLS48581G1:
fallthrough
case qcrypto.KeyTypeBLS48581G2:
blskey, err := f.blsKeyConstructor.FromBytes(key.PrivateKey, key.PublicKey)
return blskey, errors.Wrap(err, "get signing key")
// case KeyTypePCAS:
// privkey := (addressing.PCAS)(key.PrivateKey)
// return privkey, err
}
return nil, UnsupportedKeyTypeErr
}
// PutRawKey implements KeyManager
func (f *InMemoryKeyManager) PutRawKey(key *keys.Key) error {
return f.save(key.Id, *key)
}
// DeleteKey implements KeyManager
func (f *InMemoryKeyManager) DeleteKey(id string) error {
delete(f.store, id)
return nil
}
// GetKey implements KeyManager
func (f *InMemoryKeyManager) GetKey(id string) (key *keys.Key, err error) {
storeKey, err := f.read(id)
if err != nil {
return nil, err
}
return &storeKey, nil
}
// ListKeys implements KeyManager
func (f *InMemoryKeyManager) ListKeys() ([]*keys.Key, error) {
keys := []*keys.Key{}
for k := range f.store {
if len(k) == 0 {
continue
}
storeKey, err := f.read(k)
if err != nil {
return nil, err
}
keys = append(keys, &storeKey)
}
return keys, nil
}
func (f *InMemoryKeyManager) Aggregate(
publicKeys [][]byte,
signatures [][]byte,
) (
qcrypto.BlsAggregateOutput,
error,
) {
aggregate, err := f.blsKeyConstructor.Aggregate(publicKeys, signatures)
if err != nil {
return nil, errors.Wrap(err, "aggregate")
}
return aggregate, nil
}
var _ keys.KeyManager = (*InMemoryKeyManager)(nil)
func (f *InMemoryKeyManager) save(id string, key keys.Key) error {
f.store[id] = keys.Key{
Id: key.Id,
Type: key.Type,
PublicKey: key.PublicKey,
PrivateKey: key.PrivateKey,
}
return nil
}
func (f *InMemoryKeyManager) read(id string) (keys.Key, error) {
k, ok := f.store[id]
if !ok {
return keys.Key{}, errors.Wrap(KeyNotFoundErr, id)
}
return keys.Key{
Id: k.Id,
Type: k.Type,
PublicKey: k.PublicKey,
PrivateKey: k.PrivateKey,
}, nil
}