|
| 1 | +//go:build ((linux && amd64) || (linux && arm64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) && bls12381 |
| 2 | + |
| 3 | +package bls12_381 |
| 4 | + |
| 5 | +import ( |
| 6 | + "bytes" |
| 7 | + "errors" |
| 8 | + "fmt" |
| 9 | + |
| 10 | + "github.com/cometbft/cometbft/v2/crypto" |
| 11 | + "github.com/cometbft/cometbft/v2/crypto/bls12381" |
| 12 | + "github.com/cometbft/cometbft/v2/crypto/tmhash" |
| 13 | + |
| 14 | + "github.com/cosmos/cosmos-sdk/codec" |
| 15 | + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" |
| 16 | +) |
| 17 | + |
| 18 | +// =============================================================================================== |
| 19 | +// Private Key |
| 20 | +// =============================================================================================== |
| 21 | + |
| 22 | +// PrivKey is a wrapper around the Ethereum BLS12-381 private key type. This |
| 23 | +// wrapper conforms to crypto.Pubkey to allow for the use of the Ethereum |
| 24 | +// BLS12-381 private key type. |
| 25 | + |
| 26 | +var ( |
| 27 | + _ cryptotypes.PrivKey = &PrivKey{} |
| 28 | + _ codec.AminoMarshaler = &PrivKey{} |
| 29 | +) |
| 30 | + |
| 31 | +// NewPrivateKeyFromBytes build a new key from the given bytes. |
| 32 | +func NewPrivateKeyFromBytes(bz []byte) (PrivKey, error) { |
| 33 | + secretKey, err := bls12381.NewPrivateKeyFromBytes(bz) |
| 34 | + if err != nil { |
| 35 | + return PrivKey{}, err |
| 36 | + } |
| 37 | + return PrivKey{ |
| 38 | + Key: secretKey.Bytes(), |
| 39 | + }, nil |
| 40 | +} |
| 41 | + |
| 42 | +// GenPrivKey generates a new key. |
| 43 | +func GenPrivKey() (PrivKey, error) { |
| 44 | + secretKey, err := bls12381.GenPrivKey() |
| 45 | + return PrivKey{ |
| 46 | + Key: secretKey.Bytes(), |
| 47 | + }, err |
| 48 | +} |
| 49 | + |
| 50 | +// Bytes returns the byte representation of the Key. |
| 51 | +func (privKey PrivKey) Bytes() []byte { |
| 52 | + return privKey.Key |
| 53 | +} |
| 54 | + |
| 55 | +// PubKey returns the private key's public key. If the privkey is not valid |
| 56 | +// it returns a nil value. |
| 57 | +func (privKey PrivKey) PubKey() cryptotypes.PubKey { |
| 58 | + secretKey, err := bls12381.NewPrivateKeyFromBytes(privKey.Key) |
| 59 | + if err != nil { |
| 60 | + return nil |
| 61 | + } |
| 62 | + |
| 63 | + return &PubKey{ |
| 64 | + Key: secretKey.PubKey().Bytes(), |
| 65 | + } |
| 66 | +} |
| 67 | + |
| 68 | +// Equals returns true if two keys are equal and false otherwise. |
| 69 | +func (privKey PrivKey) Equals(other cryptotypes.LedgerPrivKey) bool { |
| 70 | + return privKey.Type() == other.Type() && bytes.Equal(privKey.Bytes(), other.Bytes()) |
| 71 | +} |
| 72 | + |
| 73 | +// Type returns the type. |
| 74 | +func (PrivKey) Type() string { |
| 75 | + return bls12381.KeyType |
| 76 | +} |
| 77 | + |
| 78 | +// Sign signs the given byte array. If msg is larger than |
| 79 | +// MaxMsgLen, SHA256 sum will be signed instead of the raw bytes. |
| 80 | +func (privKey PrivKey) Sign(msg []byte) ([]byte, error) { |
| 81 | + secretKey, err := bls12381.NewPrivateKeyFromBytes(privKey.Key) |
| 82 | + if err != nil { |
| 83 | + return nil, err |
| 84 | + } |
| 85 | + |
| 86 | + return secretKey.Sign(msg) |
| 87 | +} |
| 88 | + |
| 89 | +// MarshalAmino overrides Amino binary marshaling. |
| 90 | +func (privKey PrivKey) MarshalAmino() ([]byte, error) { |
| 91 | + return privKey.Key, nil |
| 92 | +} |
| 93 | + |
| 94 | +// UnmarshalAmino overrides Amino binary marshaling. |
| 95 | +func (privKey *PrivKey) UnmarshalAmino(bz []byte) error { |
| 96 | + if len(bz) != bls12381.PrivKeySize { |
| 97 | + return errors.New("invalid privkey size") |
| 98 | + } |
| 99 | + privKey.Key = bz |
| 100 | + |
| 101 | + return nil |
| 102 | +} |
| 103 | + |
| 104 | +// MarshalAminoJSON overrides Amino JSON marshaling. |
| 105 | +func (privKey PrivKey) MarshalAminoJSON() ([]byte, error) { |
| 106 | + // When we marshal to Amino JSON, we don't marshal the "key" field itself, |
| 107 | + // just its contents (i.e. the key bytes). |
| 108 | + return privKey.MarshalAmino() |
| 109 | +} |
| 110 | + |
| 111 | +// UnmarshalAminoJSON overrides Amino JSON marshaling. |
| 112 | +func (privKey *PrivKey) UnmarshalAminoJSON(bz []byte) error { |
| 113 | + return privKey.UnmarshalAmino(bz) |
| 114 | +} |
| 115 | + |
| 116 | +// =============================================================================================== |
| 117 | +// Public Key |
| 118 | +// =============================================================================================== |
| 119 | + |
| 120 | +// Pubkey is a wrapper around the Ethereum BLS12-381 public key type. This |
| 121 | +// wrapper conforms to crypto.Pubkey to allow for the use of the Ethereum |
| 122 | +// BLS12-381 public key type. |
| 123 | + |
| 124 | +var _ cryptotypes.PubKey = &PubKey{} |
| 125 | + |
| 126 | +// Address returns the address of the key. |
| 127 | +// |
| 128 | +// The function will panic if the public key is invalid. |
| 129 | +func (pubKey PubKey) Address() crypto.Address { |
| 130 | + pk, _ := bls12381.NewPublicKeyFromBytes(pubKey.Key) |
| 131 | + if len(pk.Bytes()) != bls12381.PubKeySize { |
| 132 | + panic("pubkey is incorrect size") |
| 133 | + } |
| 134 | + return crypto.Address(tmhash.SumTruncated(pubKey.Key)) |
| 135 | +} |
| 136 | + |
| 137 | +// VerifySignature verifies the given signature. |
| 138 | +func (pubKey PubKey) VerifySignature(msg, sig []byte) bool { |
| 139 | + if len(sig) != bls12381.SignatureLength { |
| 140 | + return false |
| 141 | + } |
| 142 | + |
| 143 | + pubK, err := bls12381.NewPublicKeyFromBytes(pubKey.Key) |
| 144 | + if err != nil { // invalid pubkey |
| 145 | + return false |
| 146 | + } |
| 147 | + |
| 148 | + return pubK.VerifySignature(msg, sig) |
| 149 | +} |
| 150 | + |
| 151 | +// Bytes returns the byte format. |
| 152 | +func (pubKey PubKey) Bytes() []byte { |
| 153 | + return pubKey.Key |
| 154 | +} |
| 155 | + |
| 156 | +// Type returns the key's type. |
| 157 | +func (PubKey) Type() string { |
| 158 | + return bls12381.KeyType |
| 159 | +} |
| 160 | + |
| 161 | +// Equals returns true if the other's type is the same and their bytes are deeply equal. |
| 162 | +func (pubKey PubKey) Equals(other cryptotypes.PubKey) bool { |
| 163 | + return pubKey.Type() == other.Type() && bytes.Equal(pubKey.Bytes(), other.Bytes()) |
| 164 | +} |
| 165 | + |
| 166 | +// String returns Hex representation of a pubkey with it's type |
| 167 | +func (pubKey PubKey) String() string { |
| 168 | + return fmt.Sprintf("PubKeyBLS12_381{%X}", pubKey.Key) |
| 169 | +} |
0 commit comments