-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(crypto): add blst #20296
feat(crypto): add blst #20296
Changes from 7 commits
0d32fa9
fcfbdf2
4ca8cd1
b67149b
c26ec61
2b547bd
964e1bd
551b441
f255134
7d39387
d4d5120
233f4f7
16c8720
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -6,7 +6,7 @@ import ( | |||||||||||||||||||||||||
"github.com/cometbft/cometbft/crypto/encoding" | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
"cosmossdk.io/errors" | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reorder imports according to the Golang style guide. import (
cmtprotocrypto "github.com/cometbft/cometbft/api/cometbft/crypto/v1"
cmtcrypto "github.com/cometbft/cometbft/crypto"
"github.com/cometbft/cometbft/crypto/encoding"
"cosmossdk.io/errors"
bls12_381 "github.com/cosmos/cosmos-sdk/crypto/keys/bls12_381"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
) Committable suggestion
Suggested change
Toolsgolangci-lint
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
bls12_381 "github.com/cosmos/cosmos-sdk/crypto/keys/bls12_381" | ||||||||||||||||||||||||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" | ||||||||||||||||||||||||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" | ||||||||||||||||||||||||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" | ||||||||||||||||||||||||||
|
@@ -24,6 +24,10 @@ func FromCmtProtoPublicKey(protoPk cmtprotocrypto.PublicKey) (cryptotypes.PubKey | |||||||||||||||||||||||||
return &secp256k1.PubKey{ | ||||||||||||||||||||||||||
Key: protoPk.Secp256K1, | ||||||||||||||||||||||||||
}, nil | ||||||||||||||||||||||||||
case *cmtprotocrypto.PublicKey_Bls12381: | ||||||||||||||||||||||||||
return &bls12_381.PubKey{ | ||||||||||||||||||||||||||
Key: protoPk.Bls12381, | ||||||||||||||||||||||||||
}, nil | ||||||||||||||||||||||||||
default: | ||||||||||||||||||||||||||
return nil, errors.Wrapf(sdkerrors.ErrInvalidType, "cannot convert %v from Tendermint public key", protoPk) | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
@@ -44,6 +48,12 @@ func ToCmtProtoPublicKey(pk cryptotypes.PubKey) (cmtprotocrypto.PublicKey, error | |||||||||||||||||||||||||
Secp256K1: pk.Key, | ||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||
}, nil | ||||||||||||||||||||||||||
case *bls12_381.PubKey: | ||||||||||||||||||||||||||
return cmtprotocrypto.PublicKey{ | ||||||||||||||||||||||||||
Sum: &cmtprotocrypto.PublicKey_Bls12381{ | ||||||||||||||||||||||||||
Bls12381: pk.Key, | ||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||
}, nil | ||||||||||||||||||||||||||
default: | ||||||||||||||||||||||||||
return cmtprotocrypto.PublicKey{}, errors.Wrapf(sdkerrors.ErrInvalidType, "cannot convert %v to Tendermint public key", pk) | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
package bls12_381 | ||
|
||
import ( | ||
"bytes" | ||
"crypto/sha256" | ||
fmt "fmt" | ||
|
||
"github.com/cometbft/cometbft/crypto" | ||
"github.com/cometbft/cometbft/crypto/tmhash" | ||
|
||
bls12381 "github.com/cosmos/crypto/curves/bls12381" | ||
|
||
"github.com/cosmos/cosmos-sdk/codec" | ||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" | ||
) | ||
|
||
const ( | ||
PrivKeyName = "tendermint/PrivKeyEd25519" | ||
PubKeyName = "tendermint/PubKeyEd25519" | ||
// PubKeySize is the size, in bytes, of public keys as used in this package. | ||
PubKeySize = 32 | ||
// PrivKeySize is the size, in bytes, of private keys as used in this package. | ||
PrivKeySize = 64 | ||
// SignatureSize the size of an Edwards25519 signature. Namely the size of a compressed | ||
// Edwards25519 point, and a field element. Both of which are 32 bytes. | ||
SignatureSize = 64 | ||
// SeedSize is the size, in bytes, of private key seeds. These are the | ||
// private key representations used by RFC 8032. | ||
SeedSize = 32 | ||
|
||
keyType = "bls12381" | ||
) | ||
|
||
// =============================================================================================== | ||
// Private Key | ||
// =============================================================================================== | ||
|
||
// PrivKey is a wrapper around the Ethereum BLS12-381 private key type. This | ||
// wrapper conforms to crypto.Pubkey to allow for the use of the Ethereum | ||
// BLS12-381 private key type. | ||
|
||
var ( | ||
_ cryptotypes.PrivKey = &PrivKey{} | ||
_ codec.AminoMarshaler = &PrivKey{} | ||
Check failure on line 44 in crypto/keys/bls12_381/keys.go GitHub Actions / dependency-review
Check failure on line 44 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (03)
Check failure on line 44 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (00)
Check failure on line 44 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (01)
Check failure on line 44 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (02)
|
||
) | ||
|
||
// NewPrivateKeyFromBytes build a new key from the given bytes. | ||
func NewPrivateKeyFromBytes(bz []byte) (PrivKey, error) { | ||
secretKey, err := bls12381.SecretKeyFromBytes(bz) | ||
Check failure on line 49 in crypto/keys/bls12_381/keys.go GitHub Actions / dependency-review
Check failure on line 49 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (03)
Check failure on line 49 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (00)
Check failure on line 49 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (01)
|
||
if err != nil { | ||
return nil, err | ||
Check failure on line 51 in crypto/keys/bls12_381/keys.go GitHub Actions / dependency-review
Check failure on line 51 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (03)
Check failure on line 51 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (00)
Check failure on line 51 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (01)
|
||
} | ||
return secretKey.Marshal(), nil | ||
} | ||
|
||
// GenPrivKey generates a new key. | ||
func GenPrivKey() (PrivKey, error) { | ||
secretKey, err := bls12381.RandKey() | ||
Check failure on line 58 in crypto/keys/bls12_381/keys.go GitHub Actions / dependency-review
Check failure on line 58 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (03)
Check failure on line 58 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (00)
Check failure on line 58 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (01)
|
||
return PrivKey(secretKey.Marshal()), err | ||
} | ||
|
||
// Bytes returns the byte representation of the Key. | ||
func (privKey PrivKey) Bytes() []byte { | ||
return privKey | ||
Check failure on line 64 in crypto/keys/bls12_381/keys.go GitHub Actions / dependency-review
Check failure on line 64 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (03)
Check failure on line 64 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (00)
Check failure on line 64 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (01)
|
||
} | ||
|
||
// PubKey returns the private key's public key. If the privkey is not valid | ||
// it returns a nil value. | ||
func (privKey PrivKey) PubKey() cryptotypes.PubKey { | ||
secretKey, err := bls12381.SecretKeyFromBytes(privKey) | ||
Check failure on line 70 in crypto/keys/bls12_381/keys.go GitHub Actions / dependency-review
Check failure on line 70 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (03)
Check failure on line 70 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (00)
Check failure on line 70 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (01)
|
||
if err != nil { | ||
return nil | ||
} | ||
|
||
return PubKey(secretKey.PublicKey().Marshal()) | ||
} | ||
|
||
// Equals returns true if two keys are equal and false otherwise. | ||
func (privKey PrivKey) Equals(other cryptotypes.LedgerPrivKey) bool { | ||
return privKey.Type() == other.Type() && bytes.Equal(privKey.Bytes(), other.Bytes()) | ||
} | ||
|
||
// Type returns the type. | ||
func (PrivKey) Type() string { | ||
return KeyType | ||
Check failure on line 85 in crypto/keys/bls12_381/keys.go GitHub Actions / dependency-review
Check failure on line 85 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (03)
Check failure on line 85 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (00)
Check failure on line 85 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (01)
|
||
} | ||
|
||
// Sign signs the given byte array. If msg is larger than | ||
// MaxMsgLen, SHA256 sum will be signed instead of the raw bytes. | ||
func (privKey PrivKey) Sign(msg []byte) ([]byte, error) { | ||
secretKey, err := bls12381.SecretKeyFromBytes(privKey) | ||
Check failure on line 91 in crypto/keys/bls12_381/keys.go GitHub Actions / dependency-review
Check failure on line 91 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (03)
Check failure on line 91 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (00)
Check failure on line 91 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (01)
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if len(msg) > MaxMsgLen { | ||
Check failure on line 96 in crypto/keys/bls12_381/keys.go GitHub Actions / dependency-review
Check failure on line 96 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (03)
Check failure on line 96 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (00)
Check failure on line 96 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (01)
|
||
hash := sha256.Sum256(msg) | ||
sig := secretKey.Sign(hash[:]) | ||
return sig.Marshal(), nil | ||
} | ||
sig := secretKey.Sign(msg) | ||
return sig.Marshal(), nil | ||
} | ||
|
||
// =============================================================================================== | ||
// Public Key | ||
// =============================================================================================== | ||
|
||
// Pubkey is a wrapper around the Ethereum BLS12-381 public key type. This | ||
// wrapper conforms to crypto.Pubkey to allow for the use of the Ethereum | ||
// BLS12-381 public key type. | ||
|
||
var _ cryptotypes.PubKey = &PubKey{} | ||
|
||
// Address returns the address of the key. | ||
// | ||
// The function will panic if the public key is invalid. | ||
func (pubKey PubKey) Address() crypto.Address { | ||
pk, _ := bls12381.PublicKeyFromBytes(pubKey) | ||
Check failure on line 119 in crypto/keys/bls12_381/keys.go GitHub Actions / dependency-review
Check failure on line 119 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (03)
Check failure on line 119 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (00)
Check failure on line 119 in crypto/keys/bls12_381/keys.go GitHub Actions / tests (01)
|
||
if len(pk.Marshal()) != PubKeySize { | ||
panic("pubkey is incorrect size") | ||
|
||
} | ||
return crypto.Address(tmhash.SumTruncated(pubKey)) | ||
} | ||
|
||
// VerifySignature verifies the given signature. | ||
func (pubKey PubKey) VerifySignature(msg, sig []byte) bool { | ||
if len(sig) != SignatureLength { | ||
return false | ||
} | ||
|
||
pubK, err := bls12381.PublicKeyFromBytes(pubKey) | ||
if err != nil { // invalid pubkey | ||
return false | ||
} | ||
|
||
if len(msg) > MaxMsgLen { | ||
hash := sha256.Sum256(msg) | ||
msg = hash[:] | ||
} | ||
|
||
ok, err := bls12381.VerifySignature(sig, [MaxMsgLen]byte(msg[:MaxMsgLen]), pubK) | ||
if err != nil { // bad signature | ||
return false | ||
} | ||
|
||
return ok | ||
} | ||
|
||
// Bytes returns the byte format. | ||
func (pubKey PubKey) Bytes() []byte { | ||
return pubKey | ||
} | ||
|
||
// Type returns the key's type. | ||
func (PubKey) Type() string { | ||
return KeyType | ||
} | ||
|
||
// Equals returns true if the other's type is the same and their bytes are deeply equal. | ||
func (pubKey PubKey) Equals(other cryptotypes.PubKey) bool { | ||
return pubKey.Type() == other.Type() && bytes.Equal(pubKey.Bytes(), other.Bytes()) | ||
} | ||
|
||
// String returns Hex representation of a pubkey with it's type | ||
func (pubKey PubKey) String() string { | ||
return fmt.Sprintf("PubKeyBLS12_381{%X}", pubKey.Key) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix import ordering as per project conventions.
Committable suggestion
Tools
golangci-lint