mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-21 18:37:26 +08:00
* 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
329 lines
7.6 KiB
Go
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
|
|
}
|