Documentation ¶
Overview ¶
Package secp256k1 implements optimized secp256k1 elliptic curve operations in pure Go.
This package provides an optimized pure Go implementation of elliptic curve cryptography operations over the secp256k1 curve as well as data structures and functions for working with public and private secp256k1 keys. See https://www.secg.org/sec2-v2.pdf for details on the standard.
In addition, sub packages are provided to produce, verify, parse, and serialize ECDSA signatures and EC-Schnorr-DCRv0 (a custom Schnorr-based signature scheme specific to Decred) signatures. See the README.md files in the relevant sub packages for more details about those aspects.
An overview of the features provided by this package are as follows:
- Private key generation, serialization, and parsing
- Public key generation, serialization and parsing per ANSI X9.62-1998
- Parses uncompressed, compressed, and hybrid public keys
- Serializes uncompressed and compressed public keys
- Specialized types for performing optimized and constant time field operations
- FieldVal type for working modulo the secp256k1 field prime
- ModNScalar type for working modulo the secp256k1 group order
- Elliptic curve operations in Jacobian projective coordinates
- Point addition
- Point doubling
- Scalar multiplication with an arbitrary point
- Scalar multiplication with the base point (group generator)
- Point decompression from a given x coordinate
- Nonce generation via RFC6979 with support for extra data and version information that can be used to prevent nonce reuse between signing algorithms
It also provides an implementation of the Go standard library crypto/elliptic Curve interface via the S256 function so that it may be used with other packages in the standard library such as crypto/tls, crypto/x509, and crypto/ecdsa. However, in the case of ECDSA, it is highly recommended to use the ecdsa sub package of this package instead since it is optimized specifically for secp256k1 and is significantly faster as a result.
This package also provides data structures and functions necessary to produce and verify deterministic canonical signatures in accordance with RFC6979 and BIP0062, optimized specifically for the secp256k1 curve using the Elliptic Curve Digital Signature Algorithm (ECDSA), as defined in FIPS 186-3. See https://www.secg.org/sec2-v2.pdf for details on the secp256k1 standard.
It also provides functions to parse and serialize the ECDSA signatures with the more strict Distinguished Encoding Rules (DER) of ISO/IEC 8825-1 and some additional restrictions specific to secp256k1.
In addition, it supports a custom "compact" signature format which allows efficient recovery of the public key from a given valid signature and message hash combination.
A comprehensive suite of tests is provided to ensure proper functionality. Finally, a comprehensive suite of tests is provided to provide a high level of quality assurance.
Example (EncryptDecryptMessage) ¶
This example demonstrates use of GenerateSharedSecret to encrypt a message for a recipient's public key, and subsequently decrypt the message using the recipient's private key.
package main import ( "crypto/aes" "crypto/cipher" "crypto/sha256" "encoding/binary" "encoding/hex" "fmt" "github.com/ModChain/secp256k1" ) func main() { newAEAD := func(key []byte) (cipher.AEAD, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } return cipher.NewGCM(block) } // Decode the hex-encoded pubkey of the recipient. pubKeyBytes, err := hex.DecodeString("04115c42e757b2efb7671c578530ec191a1" + "359381e6a71127a9d37c486fd30dae57e76dc58f693bd7e7010358ce6b165e483a29" + "21010db67ac11b1b51b651953d2") // uncompressed pubkey if err != nil { fmt.Println(err) return } pubKey, err := secp256k1.ParsePubKey(pubKeyBytes) if err != nil { fmt.Println(err) return } // Derive an ephemeral public/private keypair for performing ECDHE with // the recipient. ephemeralPrivKey, err := secp256k1.GeneratePrivateKey() if err != nil { fmt.Println(err) return } ephemeralPubKey := ephemeralPrivKey.PubKey().SerializeCompressed() // Using ECDHE, derive a shared symmetric key for encryption of the plaintext. cipherKey := sha256.Sum256(secp256k1.GenerateSharedSecret(ephemeralPrivKey, pubKey)) // Seal the message using an AEAD. Here we use AES-256-GCM. // The ephemeral public key must be included in this message, and becomes // the authenticated data for the AEAD. // // Note that unless a unique nonce can be guaranteed, the ephemeral // and/or shared keys must not be reused to encrypt different messages. // Doing so destroys the security of the scheme. Random nonces may be // used if XChaCha20-Poly1305 is used instead, but the message must then // also encode the nonce (which we don't do here). // // Since a new ephemeral key is generated for every message ensuring there // is no key reuse and AES-GCM permits the nonce to be used as a counter, // the nonce is intentionally initialized to all zeros so it acts like the // first (and only) use of a counter. plaintext := []byte("test message") aead, err := newAEAD(cipherKey[:]) if err != nil { fmt.Println(err) return } nonce := make([]byte, aead.NonceSize()) ciphertext := make([]byte, 4+len(ephemeralPubKey)) binary.LittleEndian.PutUint32(ciphertext, uint32(len(ephemeralPubKey))) copy(ciphertext[4:], ephemeralPubKey) ciphertext = aead.Seal(ciphertext, nonce, plaintext, ephemeralPubKey) // The remainder of this example is performed by the recipient on the // ciphertext shared by the sender. // Decode the hex-encoded private key. pkBytes, err := hex.DecodeString("a11b0a4e1a132305652ee7a8eb7848f6ad" + "5ea381e3ce20a2c086a2e388230811") if err != nil { fmt.Println(err) return } privKey := secp256k1.PrivKeyFromBytes(pkBytes) // Read the sender's ephemeral public key from the start of the message. // Error handling for inappropriate pubkey lengths is elided here for // brevity. pubKeyLen := binary.LittleEndian.Uint32(ciphertext[:4]) senderPubKeyBytes := ciphertext[4 : 4+pubKeyLen] senderPubKey, err := secp256k1.ParsePubKey(senderPubKeyBytes) if err != nil { fmt.Println(err) return } // Derive the key used to seal the message, this time from the // recipient's private key and the sender's public key. recoveredCipherKey := sha256.Sum256(secp256k1.GenerateSharedSecret(privKey, senderPubKey)) // Open the sealed message. aead, err = newAEAD(recoveredCipherKey[:]) if err != nil { fmt.Println(err) return } nonce = make([]byte, aead.NonceSize()) recoveredPlaintext, err := aead.Open(nil, nonce, ciphertext[4+pubKeyLen:], senderPubKeyBytes) if err != nil { fmt.Println(err) return } fmt.Println(string(recoveredPlaintext)) }
Output: test message
Index ¶
- Constants
- func AddNonConst(p1, p2, result *JacobianPoint)
- func DecompressY(x *FieldVal, odd bool, resultY *FieldVal) bool
- func DoubleNonConst(p, result *JacobianPoint)
- func GenerateSharedSecret(privkey *PrivateKey, pubkey *PublicKey) []byte
- func ScalarBaseMultNonConst(k *ModNScalar, result *JacobianPoint)
- func ScalarMultNonConst(k *ModNScalar, point, result *JacobianPoint)
- func SignCompact(key *PrivateKey, hash []byte, isCompressedKey bool) []bytedeprecated
- type CurveParams
- type Error
- type ErrorKind
- type FieldVal
- func (f *FieldVal) Add(val *FieldVal) *FieldVal
- func (f *FieldVal) Add2(val *FieldVal, val2 *FieldVal) *FieldVal
- func (f *FieldVal) AddInt(ui uint16) *FieldVal
- func (f *FieldVal) Bytes() *[32]byte
- func (f *FieldVal) Equals(val *FieldVal) bool
- func (f *FieldVal) Inverse() *FieldVal
- func (f *FieldVal) IsGtOrEqPrimeMinusOrder() bool
- func (f *FieldVal) IsOdd() bool
- func (f *FieldVal) IsOddBit() uint32
- func (f *FieldVal) IsOne() bool
- func (f *FieldVal) IsOneBit() uint32
- func (f *FieldVal) IsZero() bool
- func (f *FieldVal) IsZeroBit() uint32
- func (f *FieldVal) Mul(val *FieldVal) *FieldVal
- func (f *FieldVal) Mul2(val *FieldVal, val2 *FieldVal) *FieldVal
- func (f *FieldVal) MulInt(val uint8) *FieldVal
- func (f *FieldVal) Negate(magnitude uint32) *FieldVal
- func (f *FieldVal) NegateVal(val *FieldVal, magnitude uint32) *FieldVal
- func (f *FieldVal) Normalize() *FieldVal
- func (f *FieldVal) PutBytes(b *[32]byte)
- func (f *FieldVal) PutBytesUnchecked(b []byte)
- func (f *FieldVal) Set(val *FieldVal) *FieldVal
- func (f *FieldVal) SetByteSlice(b []byte) bool
- func (f *FieldVal) SetBytes(b *[32]byte) uint32
- func (f *FieldVal) SetInt(ui uint16) *FieldVal
- func (f *FieldVal) Square() *FieldVal
- func (f *FieldVal) SquareRootVal(val *FieldVal) bool
- func (f *FieldVal) SquareVal(val *FieldVal) *FieldVal
- func (f FieldVal) String() string
- func (f *FieldVal) Zero()
- type JacobianPoint
- type KoblitzCurve
- func (curve *KoblitzCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int)
- func (curve *KoblitzCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int)
- func (curve *KoblitzCurve) IsOnCurve(x, y *big.Int) bool
- func (curve *KoblitzCurve) Params() *elliptic.CurveParams
- func (curve *KoblitzCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int)
- func (curve *KoblitzCurve) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int)
- type ModNScalar
- func (s *ModNScalar) Add(val *ModNScalar) *ModNScalar
- func (s *ModNScalar) Add2(val1, val2 *ModNScalar) *ModNScalar
- func (s *ModNScalar) Bytes() [32]byte
- func (s *ModNScalar) Equals(val *ModNScalar) bool
- func (s *ModNScalar) InverseNonConst() *ModNScalar
- func (s *ModNScalar) InverseValNonConst(val *ModNScalar) *ModNScalar
- func (s *ModNScalar) IsOdd() bool
- func (s *ModNScalar) IsOverHalfOrder() bool
- func (s *ModNScalar) IsZero() bool
- func (s *ModNScalar) IsZeroBit() uint32
- func (s *ModNScalar) Mul(val *ModNScalar) *ModNScalar
- func (s *ModNScalar) Mul2(val, val2 *ModNScalar) *ModNScalar
- func (s *ModNScalar) Negate() *ModNScalar
- func (s *ModNScalar) NegateVal(val *ModNScalar) *ModNScalar
- func (s *ModNScalar) PutBytes(b *[32]byte)
- func (s *ModNScalar) PutBytesUnchecked(b []byte)
- func (s *ModNScalar) Set(val *ModNScalar) *ModNScalar
- func (s *ModNScalar) SetByteSlice(b []byte) bool
- func (s *ModNScalar) SetBytes(b *[32]byte) uint32
- func (s *ModNScalar) SetInt(ui uint32) *ModNScalar
- func (s *ModNScalar) Square() *ModNScalar
- func (s *ModNScalar) SquareVal(val *ModNScalar) *ModNScalar
- func (s ModNScalar) String() string
- func (s *ModNScalar) Zero()
- type PrivateKey
- func (privkey *PrivateKey) ECDH(remote *PublicKey) ([]byte, error)
- func (p *PrivateKey) PubKey() *PublicKey
- func (p *PrivateKey) Public() crypto.PublicKey
- func (p PrivateKey) Serialize() []byte
- func (privkey *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error)
- func (p *PrivateKey) ToECDSA() *ecdsa.PrivateKey
- func (p *PrivateKey) Zero()
- type PublicKey
- func (p *PublicKey) AsJacobian(result *JacobianPoint)
- func (p *PublicKey) IsEqual(otherPubKey *PublicKey) bool
- func (p *PublicKey) IsOnCurve() bool
- func (p PublicKey) SerializeCompressed() []byte
- func (p PublicKey) SerializeUncompressed() []byte
- func (p *PublicKey) ToECDSA() *ecdsa.PublicKey
- func (p *PublicKey) X() *big.Int
- func (p *PublicKey) Y() *big.Int
- type SignOptions
- type Signature
- func (sig *Signature) BruteforceRecoveryCode(hash []byte, pubKey *PublicKey) bool
- func (sig *Signature) Export() (*big.Int, *big.Int, byte)
- func (sig *Signature) ExportCompact(recoveryCodeFirst bool, recoveryCodeOffset byte) []byte
- func (sig *Signature) IsEqual(otherSig *Signature) bool
- func (sig *Signature) R() ModNScalar
- func (sig *Signature) RecoverPublicKey(hash []byte) (*PublicKey, error)
- func (sig *Signature) RecoveryCode() byte
- func (sig *Signature) S() ModNScalar
- func (sig *Signature) Serialize() []byte
- func (sig *Signature) Verify(hash []byte, pubKey *PublicKey) bool
- type SignatureFormat
Examples ¶
Constants ¶
const ( // ErrPubKeyInvalidLen indicates that the length of a serialized public // key is not one of the allowed lengths. ErrPubKeyInvalidLen = ErrorKind("ErrPubKeyInvalidLen") // ErrPubKeyInvalidFormat indicates an attempt was made to parse a public // key that does not specify one of the supported formats. ErrPubKeyInvalidFormat = ErrorKind("ErrPubKeyInvalidFormat") // ErrPubKeyXTooBig indicates that the x coordinate for a public key // is greater than or equal to the prime of the field underlying the group. ErrPubKeyXTooBig = ErrorKind("ErrPubKeyXTooBig") // ErrPubKeyYTooBig indicates that the y coordinate for a public key is // greater than or equal to the prime of the field underlying the group. ErrPubKeyYTooBig = ErrorKind("ErrPubKeyYTooBig") // ErrPubKeyNotOnCurve indicates that a public key is not a point on the // secp256k1 curve. ErrPubKeyNotOnCurve = ErrorKind("ErrPubKeyNotOnCurve") // ErrPubKeyMismatchedOddness indicates that a hybrid public key specified // an oddness of the y coordinate that does not match the actual oddness of // the provided y coordinate. ErrPubKeyMismatchedOddness = ErrorKind("ErrPubKeyMismatchedOddness") // ErrSigTooShort is returned when a signature that should be a DER // signature is too short. ErrSigTooShort = ErrorKind("ErrSigTooShort") // ErrSigTooLong is returned when a signature that should be a DER signature // is too long. ErrSigTooLong = ErrorKind("ErrSigTooLong") // ErrSigInvalidSeqID is returned when a signature that should be a DER // signature does not have the expected ASN.1 sequence ID. ErrSigInvalidSeqID = ErrorKind("ErrSigInvalidSeqID") // ErrSigInvalidDataLen is returned when a signature that should be a DER // signature does not specify the correct number of remaining bytes for the // R and S portions. ErrSigInvalidDataLen = ErrorKind("ErrSigInvalidDataLen") // ErrSigMissingSTypeID is returned when a signature that should be a DER // signature does not provide the ASN.1 type ID for S. ErrSigMissingSTypeID = ErrorKind("ErrSigMissingSTypeID") // ErrSigMissingSLen is returned when a signature that should be a DER // signature does not provide the length of S. ErrSigMissingSLen = ErrorKind("ErrSigMissingSLen") // ErrSigInvalidSLen is returned when a signature that should be a DER // signature does not specify the correct number of bytes for the S portion. ErrSigInvalidSLen = ErrorKind("ErrSigInvalidSLen") // ErrSigInvalidRIntID is returned when a signature that should be a DER // signature does not have the expected ASN.1 integer ID for R. ErrSigInvalidRIntID = ErrorKind("ErrSigInvalidRIntID") // ErrSigZeroRLen is returned when a signature that should be a DER // signature has an R length of zero. ErrSigZeroRLen = ErrorKind("ErrSigZeroRLen") // ErrSigNegativeR is returned when a signature that should be a DER // signature has a negative value for R. ErrSigNegativeR = ErrorKind("ErrSigNegativeR") // ErrSigTooMuchRPadding is returned when a signature that should be a DER // signature has too much padding for R. ErrSigTooMuchRPadding = ErrorKind("ErrSigTooMuchRPadding") // ErrSigRIsZero is returned when a signature has R set to the value zero. ErrSigRIsZero = ErrorKind("ErrSigRIsZero") // ErrSigRTooBig is returned when a signature has R with a value that is // greater than or equal to the group order. ErrSigRTooBig = ErrorKind("ErrSigRTooBig") // ErrSigInvalidSIntID is returned when a signature that should be a DER // signature does not have the expected ASN.1 integer ID for S. ErrSigInvalidSIntID = ErrorKind("ErrSigInvalidSIntID") // ErrSigZeroSLen is returned when a signature that should be a DER // signature has an S length of zero. ErrSigZeroSLen = ErrorKind("ErrSigZeroSLen") // ErrSigNegativeS is returned when a signature that should be a DER // signature has a negative value for S. ErrSigNegativeS = ErrorKind("ErrSigNegativeS") // ErrSigTooMuchSPadding is returned when a signature that should be a DER // signature has too much padding for S. ErrSigTooMuchSPadding = ErrorKind("ErrSigTooMuchSPadding") // ErrSigSIsZero is returned when a signature has S set to the value zero. ErrSigSIsZero = ErrorKind("ErrSigSIsZero") // ErrSigSTooBig is returned when a signature has S with a value that is // greater than or equal to the group order. ErrSigSTooBig = ErrorKind("ErrSigSTooBig") // ErrSigInvalidLen is returned when a signature that should be a compact // signature is not the required length. ErrSigInvalidLen = ErrorKind("ErrSigInvalidLen") // ErrSigInvalidRecoveryCode is returned when a signature that should be a // compact signature has an invalid value for the public key recovery code. ErrSigInvalidRecoveryCode = ErrorKind("ErrSigInvalidRecoveryCode") // ErrSigOverflowsPrime is returned when a signature that should be a // compact signature has the overflow bit set but adding the order to it // would overflow the underlying field prime. ErrSigOverflowsPrime = ErrorKind("ErrSigOverflowsPrime") // ErrPointNotOnCurve is returned when attempting to recover a public key // from a compact signature results in a point that is not on the elliptic // curve. ErrPointNotOnCurve = ErrorKind("ErrPointNotOnCurve") )
These constants are used to identify a specific RuleError.
const ( // PubKeyBytesLenCompressed is the number of bytes of a serialized // compressed public key. PubKeyBytesLenCompressed = 33 // PubKeyBytesLenUncompressed is the number of bytes of a serialized // uncompressed public key. PubKeyBytesLenUncompressed = 65 // PubKeyFormatCompressedEven is the identifier prefix byte for a public key // whose Y coordinate is even when serialized in the compressed format per // section 2.3.4 of [SEC1](https://secg.org/sec1-v2.pdf#subsubsection.2.3.4). PubKeyFormatCompressedEven byte = 0x02 // PubKeyFormatCompressedOdd is the identifier prefix byte for a public key // whose Y coordinate is odd when serialized in the compressed format per // section 2.3.4 of [SEC1](https://secg.org/sec1-v2.pdf#subsubsection.2.3.4). PubKeyFormatCompressedOdd byte = 0x03 // PubKeyFormatUncompressed is the identifier prefix byte for a public key // when serialized according in the uncompressed format per section 2.3.3 of // [SEC1](https://secg.org/sec1-v2.pdf#subsubsection.2.3.3). PubKeyFormatUncompressed byte = 0x04 // PubKeyFormatHybridEven is the identifier prefix byte for a public key // whose Y coordinate is even when serialized according to the hybrid format // per section 4.3.6 of [ANSI X9.62-1998]. // // NOTE: This format makes little sense in practice an therefore this // package will not produce public keys serialized in this format. However, // it will parse them since they exist in the wild. PubKeyFormatHybridEven byte = 0x06 // PubKeyFormatHybridOdd is the identifier prefix byte for a public key // whose Y coordingate is odd when serialized according to the hybrid format // per section 4.3.6 of [ANSI X9.62-1998]. // // NOTE: This format makes little sense in practice an therefore this // package will not produce public keys serialized in this format. However, // it will parse them since they exist in the wild. PubKeyFormatHybridOdd byte = 0x07 )
const PrivKeyBytesLen = 32
PrivKeyBytesLen defines the length in bytes of a serialized private key.
Variables ¶
This section is empty.
Functions ¶
func AddNonConst ¶
func AddNonConst(p1, p2, result *JacobianPoint)
AddNonConst adds the passed Jacobian points together and stores the result in the provided result param in *non-constant* time.
NOTE: The points must be normalized for this function to return the correct result. The resulting point will be normalized.
func DecompressY ¶
DecompressY attempts to calculate the Y coordinate for the given X coordinate such that the result pair is a point on the secp256k1 curve. It adjusts Y based on the desired oddness and returns whether or not it was successful since not all X coordinates are valid.
The magnitude of the provided X coordinate field val must be a max of 8 for a correct result. The resulting Y field val will have a max magnitude of 2.
func DoubleNonConst ¶
func DoubleNonConst(p, result *JacobianPoint)
DoubleNonConst doubles the passed Jacobian point and stores the result in the provided result parameter in *non-constant* time.
NOTE: The point must be normalized for this function to return the correct result. The resulting point will be normalized.
func GenerateSharedSecret ¶
func GenerateSharedSecret(privkey *PrivateKey, pubkey *PublicKey) []byte
GenerateSharedSecret generates a shared secret based on a private key and a public key using Diffie-Hellman key exchange (ECDH) (RFC 5903). RFC5903 Section 9 states we should only return x.
It is recommended to securely hash the result before using as a cryptographic key.
func ScalarBaseMultNonConst ¶
func ScalarBaseMultNonConst(k *ModNScalar, result *JacobianPoint)
ScalarBaseMultNonConst multiplies k*G where k is a scalar modulo the curve order and G is the base point of the group and stores the result in the provided Jacobian point.
NOTE: The resulting point will be normalized.
func ScalarMultNonConst ¶
func ScalarMultNonConst(k *ModNScalar, point, result *JacobianPoint)
ScalarMultNonConst multiplies k*P where k is a scalar modulo the curve order and P is a point in Jacobian projective coordinates and stores the result in the provided Jacobian point.
NOTE: The point must be normalized for this function to return the correct result. The resulting point will be normalized.
func SignCompact
deprecated
added in
v0.2.0
func SignCompact(key *PrivateKey, hash []byte, isCompressedKey bool) []byte
SignCompact produces a compact ECDSA signature over the secp256k1 curve for the provided hash (which should be the result of hashing a larger message) using the given private key. The isCompressedKey parameter specifies if the produced signature should reference a compressed public key or not.
Compact signature format: <1-byte compact sig recovery code><32-byte R><32-byte S>
The compact sig recovery code is the value 27 + public key recovery code + 4 if the compact signature was created with a compressed public key.
Deprecated: use Sign and Signature.ExportCompact instead
Types ¶
type CurveParams ¶
type CurveParams struct { // P is the prime used in the secp256k1 field. P *big.Int // N is the order of the secp256k1 curve group generated by the base point. N *big.Int // Gx and Gy are the x and y coordinate of the base point, respectively. Gx, Gy *big.Int // BitSize is the size of the underlying secp256k1 field in bits. BitSize int // H is the cofactor of the secp256k1 curve. H int // ByteSize is simply the bit size / 8 and is provided for convenience // since it is calculated repeatedly. ByteSize int }
CurveParams contains the parameters for the secp256k1 curve.
func Params ¶
func Params() *CurveParams
Params returns the secp256k1 curve parameters for convenience.
type Error ¶
Error identifies an error related to public key cryptography using a sec256k1 curve. It has full support for errors.Is and errors.As, so the caller can ascertain the specific reason for the error by checking the underlying error.
type ErrorKind ¶
type ErrorKind string
ErrorKind identifies a kind of error. It has full support for errors.Is and errors.As, so the caller can directly check against an error kind when determining the reason for an error.
type FieldVal ¶
type FieldVal struct {
// contains filtered or unexported fields
}
FieldVal implements optimized fixed-precision arithmetic over the secp256k1 finite field. This means all arithmetic is performed modulo
0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f.
WARNING: Since it is so important for the field arithmetic to be extremely fast for high performance crypto, this type does not perform any validation of documented preconditions where it ordinarily would. As a result, it is IMPERATIVE for callers to understand some key concepts that are described below and ensure the methods are called with the necessary preconditions that each method is documented with. For example, some methods only give the correct result if the field value is normalized and others require the field values involved to have a maximum magnitude and THERE ARE NO EXPLICIT CHECKS TO ENSURE THOSE PRECONDITIONS ARE SATISFIED. This does, unfortunately, make the type more difficult to use correctly and while I typically prefer to ensure all state and input is valid for most code, this is a bit of an exception because those extra checks really add up in what ends up being critical hot paths.
The first key concept when working with this type is normalization. In order to avoid the need to propagate a ton of carries, the internal representation provides additional overflow bits for each word of the overall 256-bit value. This means that there are multiple internal representations for the same value and, as a result, any methods that rely on comparison of the value, such as equality and oddness determination, require the caller to provide a normalized value.
The second key concept when working with this type is magnitude. As previously mentioned, the internal representation provides additional overflow bits which means that the more math operations that are performed on the field value between normalizations, the more those overflow bits accumulate. The magnitude is effectively that maximum possible number of those overflow bits that could possibly be required as a result of a given operation. Since there are only a limited number of overflow bits available, this implies that the max possible magnitude MUST be tracked by the caller and the caller MUST normalize the field value if a given operation would cause the magnitude of the result to exceed the max allowed value.
IMPORTANT: The max allowed magnitude of a field value is 64.
func (*FieldVal) Add ¶
Add adds the passed value to the existing field value and stores the result in f in constant time.
The field value is returned to support chaining. This enables syntax like: f.Add(f2).AddInt(1) so that f = f + f2 + 1.
Preconditions: - The sum of the magnitudes of the two field values MUST be a max of 64 Output Normalized: No Output Max Magnitude: Sum of the magnitude of the two individual field values
func (*FieldVal) Add2 ¶
Add2 adds the passed two field values together and stores the result in f in constant time.
The field value is returned to support chaining. This enables syntax like: f3.Add2(f, f2).AddInt(1) so that f3 = f + f2 + 1.
Preconditions: - The sum of the magnitudes of the two field values MUST be a max of 64 Output Normalized: No Output Max Magnitude: Sum of the magnitude of the two field values
func (*FieldVal) AddInt ¶
AddInt adds the passed integer to the existing field value and stores the result in f in constant time. This is a convenience function since it is fairly common to perform some arithmetic with small native integers.
The field value is returned to support chaining. This enables syntax like: f.AddInt(1).Add(f2) so that f = f + 1 + f2.
Preconditions: - The field value MUST have a max magnitude of 63 Output Normalized: No Output Max Magnitude: Existing field magnitude + 1
func (*FieldVal) Bytes ¶
Bytes unpacks the field value to a 32-byte big-endian value in constant time.
See PutBytes and PutBytesUnchecked for variants that allow an array or slice to be passed which can be useful to cut down on the number of allocations by allowing the caller to reuse a buffer or write directly into part of a larger buffer.
Preconditions: - The field value MUST be normalized
func (*FieldVal) Equals ¶
Equals returns whether or not the two field values are the same in constant time.
Preconditions: - Both field values being compared MUST be normalized
func (*FieldVal) Inverse ¶
Inverse finds the modular multiplicative inverse of the field value in constant time. The existing field value is modified.
The field value is returned to support chaining. This enables syntax like: f.Inverse().Mul(f2) so that f = f^-1 * f2.
Preconditions: - The field value MUST have a max magnitude of 8 Output Normalized: No Output Max Magnitude: 1
func (*FieldVal) IsGtOrEqPrimeMinusOrder ¶
IsGtOrEqPrimeMinusOrder returns whether or not the field value exceeds the group order divided by 2 in constant time.
Preconditions: - The field value MUST be normalized
func (*FieldVal) IsOdd ¶
IsOdd returns whether or not the field value is an odd number in constant time.
Preconditions: - The field value MUST be normalized
func (*FieldVal) IsOddBit ¶
IsOddBit returns 1 when the field value is an odd number or 0 otherwise in constant time.
Note that a bool is not used here because it is not possible in Go to convert from a bool to numeric value in constant time and many constant-time operations require a numeric value. See IsOdd for the version that returns a bool.
Preconditions: - The field value MUST be normalized
func (*FieldVal) IsOne ¶
IsOne returns whether or not the field value is equal to one in constant time.
Preconditions: - The field value MUST be normalized
func (*FieldVal) IsOneBit ¶
IsOneBit returns 1 when the field value is equal to one or 0 otherwise in constant time.
Note that a bool is not used here because it is not possible in Go to convert from a bool to numeric value in constant time and many constant-time operations require a numeric value. See IsOne for the version that returns a bool.
Preconditions: - The field value MUST be normalized
func (*FieldVal) IsZero ¶
IsZero returns whether or not the field value is equal to zero in constant time.
Preconditions: - The field value MUST be normalized
func (*FieldVal) IsZeroBit ¶
IsZeroBit returns 1 when the field value is equal to zero or 0 otherwise in constant time.
Note that a bool is not used here because it is not possible in Go to convert from a bool to numeric value in constant time and many constant-time operations require a numeric value. See IsZero for the version that returns a bool.
Preconditions: - The field value MUST be normalized
func (*FieldVal) Mul ¶
Mul multiplies the passed value to the existing field value and stores the result in f in constant time. Note that this function can overflow if multiplying any of the individual words exceeds a max uint32. In practice, this means the magnitude of either value involved in the multiplication must be a max of 8.
The field value is returned to support chaining. This enables syntax like: f.Mul(f2).AddInt(1) so that f = (f * f2) + 1.
Preconditions: - Both field values MUST have a max magnitude of 8 Output Normalized: No Output Max Magnitude: 1
func (*FieldVal) Mul2 ¶
Mul2 multiplies the passed two field values together and stores the result in f in constant time. Note that this function can overflow if multiplying any of the individual words exceeds a max uint32. In practice, this means the magnitude of either value involved in the multiplication must be a max of 8.
The field value is returned to support chaining. This enables syntax like: f3.Mul2(f, f2).AddInt(1) so that f3 = (f * f2) + 1.
Preconditions: - Both input field values MUST have a max magnitude of 8 Output Normalized: No Output Max Magnitude: 1
func (*FieldVal) MulInt ¶
MulInt multiplies the field value by the passed int and stores the result in f in constant time. Note that this function can overflow if multiplying the value by any of the individual words exceeds a max uint32. Therefore it is important that the caller ensures no overflows will occur before using this function.
The field value is returned to support chaining. This enables syntax like: f.MulInt(2).Add(f2) so that f = 2 * f + f2.
Preconditions: - The field value magnitude multiplied by given val MUST be a max of 64 Output Normalized: No Output Max Magnitude: Existing field magnitude times the provided integer val
func (*FieldVal) Negate ¶
Negate negates the field value in constant time. The existing field value is modified. The caller must provide the magnitude of the field value for a correct result.
The field value is returned to support chaining. This enables syntax like: f.Negate().AddInt(1) so that f = -f + 1.
Preconditions: - The max magnitude MUST be 63 Output Normalized: No Output Max Magnitude: Input magnitude + 1
func (*FieldVal) NegateVal ¶
NegateVal negates the passed value and stores the result in f in constant time. The caller must provide the magnitude of the passed value for a correct result.
The field value is returned to support chaining. This enables syntax like: f.NegateVal(f2).AddInt(1) so that f = -f2 + 1.
Preconditions: - The max magnitude MUST be 63 Output Normalized: No Output Max Magnitude: Input magnitude + 1
func (*FieldVal) Normalize ¶
Normalize normalizes the internal field words into the desired range and performs fast modular reduction over the secp256k1 prime by making use of the special form of the prime in constant time.
Preconditions: None Output Normalized: Yes Output Max Magnitude: 1
func (*FieldVal) PutBytes ¶
PutBytes unpacks the field value to a 32-byte big-endian value using the passed byte array in constant time.
There is a similar function, PutBytesUnchecked, which unpacks the field value into a slice that must have at least 32 bytes available. This version is provided since it can be useful to write directly into an array that is type checked.
Alternatively, there is also Bytes, which unpacks the field value into a new array and returns that which can sometimes be more ergonomic in applications that aren't concerned about an additional copy.
Preconditions: - The field value MUST be normalized
func (*FieldVal) PutBytesUnchecked ¶
PutBytesUnchecked unpacks the field value to a 32-byte big-endian value directly into the passed byte slice in constant time. The target slice must have at least 32 bytes available or it will panic.
There is a similar function, PutBytes, which unpacks the field value into a 32-byte array directly. This version is provided since it can be useful to write directly into part of a larger buffer without needing a separate allocation.
Preconditions: - The field value MUST be normalized - The target slice MUST have at least 32 bytes available
func (*FieldVal) Set ¶
Set sets the field value equal to the passed value in constant time. The normalization and magnitude of the two fields will be identical.
The field value is returned to support chaining. This enables syntax like: f := new(FieldVal).Set(f2).Add(1) so that f = f2 + 1 where f2 is not modified.
Preconditions: None Output Normalized: Same as input value Output Max Magnitude: Same as input value
func (*FieldVal) SetByteSlice ¶
SetByteSlice interprets the provided slice as a 256-bit big-endian unsigned integer (meaning it is truncated to the first 32 bytes), packs it into the internal field value representation, and returns whether or not the resulting truncated 256-bit integer is greater than or equal to the field prime (aka it overflowed) in constant time.
Note that since passing a slice with more than 32 bytes is truncated, it is possible that the truncated value is less than the field prime and hence it will not be reported as having overflowed in that case. It is up to the caller to decide whether it needs to provide numbers of the appropriate size or it if is acceptable to use this function with the described truncation and overflow behavior.
Preconditions: None Output Normalized: Yes if no overflow, no otherwise Output Max Magnitude: 1
func (*FieldVal) SetBytes ¶
SetBytes packs the passed 32-byte big-endian value into the internal field value representation in constant time. SetBytes interprets the provided array as a 256-bit big-endian unsigned integer, packs it into the internal field value representation, and returns either 1 if it is greater than or equal to the field prime (aka it overflowed) or 0 otherwise in constant time.
Note that a bool is not used here because it is not possible in Go to convert from a bool to numeric value in constant time and many constant-time operations require a numeric value.
Preconditions: None Output Normalized: Yes if no overflow, no otherwise Output Max Magnitude: 1
func (*FieldVal) SetInt ¶
SetInt sets the field value to the passed integer in constant time. This is a convenience function since it is fairly common to perform some arithmetic with small native integers.
The field value is returned to support chaining. This enables syntax such as f := new(FieldVal).SetInt(2).Mul(f2) so that f = 2 * f2.
Preconditions: None Output Normalized: Yes Output Max Magnitude: 1
func (*FieldVal) Square ¶
Square squares the field value in constant time. The existing field value is modified. Note that this function can overflow if multiplying any of the individual words exceeds a max uint32. In practice, this means the magnitude of the field must be a max of 8 to prevent overflow.
The field value is returned to support chaining. This enables syntax like: f.Square().Mul(f2) so that f = f^2 * f2.
Preconditions: - The field value MUST have a max magnitude of 8 Output Normalized: No Output Max Magnitude: 1
func (*FieldVal) SquareRootVal ¶
SquareRootVal either calculates the square root of the passed value when it exists or the square root of the negation of the value when it does not exist and stores the result in f in constant time. The return flag is true when the calculated square root is for the passed value itself and false when it is for its negation.
Note that this function can overflow if multiplying any of the individual words exceeds a max uint32. In practice, this means the magnitude of the field must be a max of 8 to prevent overflow. The magnitude of the result will be 1.
Preconditions: - The input field value MUST have a max magnitude of 8 Output Normalized: No Output Max Magnitude: 1
func (*FieldVal) SquareVal ¶
SquareVal squares the passed value and stores the result in f in constant time. Note that this function can overflow if multiplying any of the individual words exceeds a max uint32. In practice, this means the magnitude of the field being squared must be a max of 8 to prevent overflow.
The field value is returned to support chaining. This enables syntax like: f3.SquareVal(f).Mul(f) so that f3 = f^2 * f = f^3.
Preconditions: - The input field value MUST have a max magnitude of 8 Output Normalized: No Output Max Magnitude: 1
type JacobianPoint ¶
type JacobianPoint struct { // The X coordinate in Jacobian projective coordinates. The affine point is // X/z^2. X FieldVal // The Y coordinate in Jacobian projective coordinates. The affine point is // Y/z^3. Y FieldVal // The Z coordinate in Jacobian projective coordinates. Z FieldVal }
JacobianPoint is an element of the group formed by the secp256k1 curve in Jacobian projective coordinates and thus represents a point on the curve.
func MakeJacobianPoint ¶
func MakeJacobianPoint(x, y, z *FieldVal) JacobianPoint
MakeJacobianPoint returns a Jacobian point with the provided X, Y, and Z coordinates.
func (*JacobianPoint) Set ¶
func (p *JacobianPoint) Set(other *JacobianPoint)
Set sets the Jacobian point to the provided point.
func (*JacobianPoint) ToAffine ¶
func (p *JacobianPoint) ToAffine()
ToAffine reduces the Z value of the existing point to 1 effectively making it an affine coordinate in constant time. The point will be normalized.
type KoblitzCurve ¶
type KoblitzCurve struct {
*elliptic.CurveParams
}
KoblitzCurve provides an implementation for secp256k1 that fits the ECC Curve interface from crypto/elliptic.
func (*KoblitzCurve) Add ¶
Add returns the sum of (x1,y1) and (x2,y2).
This is part of the elliptic.Curve interface implementation.
func (*KoblitzCurve) Double ¶
Double returns 2*(x1,y1).
This is part of the elliptic.Curve interface implementation.
func (*KoblitzCurve) IsOnCurve ¶
func (curve *KoblitzCurve) IsOnCurve(x, y *big.Int) bool
IsOnCurve returns whether or not the affine point (x,y) is on the curve.
This is part of the elliptic.Curve interface implementation. This function differs from the crypto/elliptic algorithm since a = 0 not -3.
func (*KoblitzCurve) Params ¶
func (curve *KoblitzCurve) Params() *elliptic.CurveParams
Params returns the parameters for the curve.
This is part of the elliptic.Curve interface implementation.
func (*KoblitzCurve) ScalarBaseMult ¶
ScalarBaseMult returns k*G where G is the base point of the group and k is a big endian integer.
This is part of the elliptic.Curve interface implementation.
func (*KoblitzCurve) ScalarMult ¶
ScalarMult returns k*(Bx, By) where k is a big endian integer.
This is part of the elliptic.Curve interface implementation.
type ModNScalar ¶
type ModNScalar struct {
// contains filtered or unexported fields
}
ModNScalar implements optimized 256-bit constant-time fixed-precision arithmetic over the secp256k1 group order. This means all arithmetic is performed modulo:
0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
It only implements the arithmetic needed for elliptic curve operations, however, the operations that are not implemented can typically be worked around if absolutely needed. For example, subtraction can be performed by adding the negation.
Should it be absolutely necessary, conversion to the standard library math/big.Int can be accomplished by using the Bytes method, slicing the resulting fixed-size array, and feeding it to big.Int.SetBytes. However, that should typically be avoided when possible as conversion to big.Ints requires allocations, is not constant time, and is slower when working modulo the group order.
func NonceRFC6979 ¶
func NonceRFC6979(privKey []byte, hash []byte, extra []byte, version []byte, extraIterations uint32) *ModNScalar
NonceRFC6979 generates a nonce deterministically according to RFC 6979 using HMAC-SHA256 for the hashing function. It takes a 32-byte hash as an input and returns a 32-byte nonce to be used for deterministic signing. The extra and version arguments are optional, but allow additional data to be added to the input of the HMAC. When provided, the extra data must be 32-bytes and version must be 16 bytes or they will be ignored.
Finally, the extraIterations parameter provides a method to produce a stream of deterministic nonces to ensure the signing code is able to produce a nonce that results in a valid signature in the extremely unlikely event the original nonce produced results in an invalid signature (e.g. R == 0). Signing code should start with 0 and increment it if necessary.
func (*ModNScalar) Add ¶
func (s *ModNScalar) Add(val *ModNScalar) *ModNScalar
Add adds the passed scalar to the existing one modulo the group order in constant time and stores the result in s.
The scalar is returned to support chaining. This enables syntax like: s.Add(s2).AddInt(1) so that s = s + s2 + 1.
func (*ModNScalar) Add2 ¶
func (s *ModNScalar) Add2(val1, val2 *ModNScalar) *ModNScalar
Add2 adds the passed two scalars together modulo the group order in constant time and stores the result in s.
The scalar is returned to support chaining. This enables syntax like: s3.Add2(s, s2).AddInt(1) so that s3 = s + s2 + 1.
func (*ModNScalar) Bytes ¶
func (s *ModNScalar) Bytes() [32]byte
Bytes unpacks the scalar to a 32-byte big-endian value in constant time.
See PutBytes and PutBytesUnchecked for variants that allow an array or slice to be passed which can be useful to cut down on the number of allocations by allowing the caller to reuse a buffer or write directly into part of a larger buffer.
func (*ModNScalar) Equals ¶
func (s *ModNScalar) Equals(val *ModNScalar) bool
Equals returns whether or not the two scalars are the same in constant time.
func (*ModNScalar) InverseNonConst ¶
func (s *ModNScalar) InverseNonConst() *ModNScalar
InverseNonConst finds the modular multiplicative inverse of the scalar in *non-constant* time. The existing scalar is modified.
The scalar is returned to support chaining. This enables syntax like: s.Inverse().Mul(s2) so that s = s^-1 * s2.
func (*ModNScalar) InverseValNonConst ¶
func (s *ModNScalar) InverseValNonConst(val *ModNScalar) *ModNScalar
InverseValNonConst finds the modular multiplicative inverse of the passed scalar and stores result in s in *non-constant* time.
The scalar is returned to support chaining. This enables syntax like: s3.InverseVal(s1).Mul(s2) so that s3 = s1^-1 * s2.
func (*ModNScalar) IsOdd ¶
func (s *ModNScalar) IsOdd() bool
IsOdd returns whether or not the scalar is an odd number in constant time.
func (*ModNScalar) IsOverHalfOrder ¶
func (s *ModNScalar) IsOverHalfOrder() bool
IsOverHalfOrder returns whether or not the scalar exceeds the group order divided by 2 in constant time.
func (*ModNScalar) IsZero ¶
func (s *ModNScalar) IsZero() bool
IsZero returns whether or not the scalar is equal to zero in constant time.
func (*ModNScalar) IsZeroBit ¶
func (s *ModNScalar) IsZeroBit() uint32
IsZeroBit returns 1 when the scalar is equal to zero or 0 otherwise in constant time.
Note that a bool is not used here because it is not possible in Go to convert from a bool to numeric value in constant time and many constant-time operations require a numeric value. See IsZero for the version that returns a bool.
func (*ModNScalar) Mul ¶
func (s *ModNScalar) Mul(val *ModNScalar) *ModNScalar
Mul multiplies the passed scalar with the existing one modulo the group order in constant time and stores the result in s.
The scalar is returned to support chaining. This enables syntax like: s.Mul(s2).AddInt(1) so that s = (s * s2) + 1.
func (*ModNScalar) Mul2 ¶
func (s *ModNScalar) Mul2(val, val2 *ModNScalar) *ModNScalar
Mul2 multiplies the passed two scalars together modulo the group order in constant time and stores the result in s.
The scalar is returned to support chaining. This enables syntax like: s3.Mul2(s, s2).AddInt(1) so that s3 = (s * s2) + 1.
func (*ModNScalar) Negate ¶
func (s *ModNScalar) Negate() *ModNScalar
Negate negates the scalar modulo the group order in constant time. The existing scalar is modified.
The scalar is returned to support chaining. This enables syntax like: s.Negate().AddInt(1) so that s = -s + 1.
func (*ModNScalar) NegateVal ¶
func (s *ModNScalar) NegateVal(val *ModNScalar) *ModNScalar
NegateVal negates the passed scalar modulo the group order and stores the result in s in constant time.
The scalar is returned to support chaining. This enables syntax like: s.NegateVal(s2).AddInt(1) so that s = -s2 + 1.
func (*ModNScalar) PutBytes ¶
func (s *ModNScalar) PutBytes(b *[32]byte)
PutBytes unpacks the scalar to a 32-byte big-endian value using the passed byte array in constant time.
There is a similar function, PutBytesUnchecked, which unpacks the scalar into a slice that must have at least 32 bytes available. This version is provided since it can be useful to write directly into an array that is type checked.
Alternatively, there is also Bytes, which unpacks the scalar into a new array and returns that which can sometimes be more ergonomic in applications that aren't concerned about an additional copy.
func (*ModNScalar) PutBytesUnchecked ¶
func (s *ModNScalar) PutBytesUnchecked(b []byte)
PutBytesUnchecked unpacks the scalar to a 32-byte big-endian value directly into the passed byte slice in constant time. The target slice must have at least 32 bytes available or it will panic.
There is a similar function, PutBytes, which unpacks the scalar into a 32-byte array directly. This version is provided since it can be useful to write directly into part of a larger buffer without needing a separate allocation.
Preconditions:
- The target slice MUST have at least 32 bytes available
func (*ModNScalar) Set ¶
func (s *ModNScalar) Set(val *ModNScalar) *ModNScalar
Set sets the scalar equal to a copy of the passed one in constant time.
The scalar is returned to support chaining. This enables syntax like: s := new(ModNScalar).Set(s2).Add(1) so that s = s2 + 1 where s2 is not modified.
func (*ModNScalar) SetByteSlice ¶
func (s *ModNScalar) SetByteSlice(b []byte) bool
SetByteSlice interprets the provided slice as a 256-bit big-endian unsigned integer (meaning it is truncated to the first 32 bytes), reduces it modulo the group order, sets the scalar to the result, and returns whether or not the resulting truncated 256-bit integer overflowed in constant time.
Note that since passing a slice with more than 32 bytes is truncated, it is possible that the truncated value is less than the order of the curve and hence it will not be reported as having overflowed in that case. It is up to the caller to decide whether it needs to provide numbers of the appropriate size or it is acceptable to use this function with the described truncation and overflow behavior.
func (*ModNScalar) SetBytes ¶
func (s *ModNScalar) SetBytes(b *[32]byte) uint32
SetBytes interprets the provided array as a 256-bit big-endian unsigned integer, reduces it modulo the group order, sets the scalar to the result, and returns either 1 if it was reduced (aka it overflowed) or 0 otherwise in constant time.
Note that a bool is not used here because it is not possible in Go to convert from a bool to numeric value in constant time and many constant-time operations require a numeric value.
func (*ModNScalar) SetInt ¶
func (s *ModNScalar) SetInt(ui uint32) *ModNScalar
SetInt sets the scalar to the passed integer in constant time. This is a convenience function since it is fairly common to perform some arithmetic with small native integers.
The scalar is returned to support chaining. This enables syntax like: s := new(ModNScalar).SetInt(2).Mul(s2) so that s = 2 * s2.
func (*ModNScalar) Square ¶
func (s *ModNScalar) Square() *ModNScalar
Square squares the scalar modulo the group order in constant time. The existing scalar is modified.
The scalar is returned to support chaining. This enables syntax like: s.Square().Mul(s2) so that s = s^2 * s2.
func (*ModNScalar) SquareVal ¶
func (s *ModNScalar) SquareVal(val *ModNScalar) *ModNScalar
SquareVal squares the passed scalar modulo the group order in constant time and stores the result in s.
The scalar is returned to support chaining. This enables syntax like: s3.SquareVal(s).Mul(s) so that s3 = s^2 * s = s^3.
func (ModNScalar) String ¶
func (s ModNScalar) String() string
String returns the scalar as a human-readable hex string.
This is NOT constant time.
func (*ModNScalar) Zero ¶
func (s *ModNScalar) Zero()
Zero sets the scalar to zero in constant time. A newly created scalar is already set to zero. This function can be useful to clear an existing scalar for reuse.
type PrivateKey ¶
type PrivateKey struct {
Key ModNScalar
}
PrivateKey provides facilities for working with secp256k1 private keys within this package and includes functionality such as serializing and parsing them as well as computing their associated public key.
func GeneratePrivateKey ¶
func GeneratePrivateKey() (*PrivateKey, error)
GeneratePrivateKey generates and returns a new cryptographically secure private key that is suitable for use with secp256k1.
func GeneratePrivateKeyFromRand ¶
func GeneratePrivateKeyFromRand(rand io.Reader) (*PrivateKey, error)
GeneratePrivateKeyFromRand generates a private key that is suitable for use with secp256k1 using the provided reader as a source of entropy. The provided reader must be a source of cryptographically secure randomness, such as crypto/rand.Reader, to avoid weak private keys.
func NewPrivateKey ¶
func NewPrivateKey(key *ModNScalar) *PrivateKey
NewPrivateKey instantiates a new private key from a scalar encoded as a big integer.
func PrivKeyFromBytes ¶
func PrivKeyFromBytes(privKeyBytes []byte) *PrivateKey
PrivKeyFromBytes returns a private based on the provided byte slice which is interpreted as an unsigned 256-bit big-endian integer in the range [0, N-1], where N is the order of the curve.
WARNING: This means passing a slice with more than 32 bytes is truncated and that truncated value is reduced modulo N. Further, 0 is not a valid private key. It is up to the caller to provide a value in the appropriate range of [1, N-1]. Failure to do so will either result in an invalid private key or potentially weak private keys that have bias that could be exploited.
This function primarily exists to provide a mechanism for converting serialized private keys that are already known to be good.
Typically callers should make use of GeneratePrivateKey or GeneratePrivateKeyFromRand when creating private keys since they properly handle generation of appropriate values.
func (*PrivateKey) ECDH ¶ added in v0.2.1
func (privkey *PrivateKey) ECDH(remote *PublicKey) ([]byte, error)
ECDH generates a shared secret and is an alias to GenerateSharedSecret, however by being part of the private key it is closer to go's own ecdh api.
func (*PrivateKey) PubKey ¶
func (p *PrivateKey) PubKey() *PublicKey
PubKey computes and returns the public key corresponding to this private key.
func (*PrivateKey) Public ¶ added in v0.2.1
func (p *PrivateKey) Public() crypto.PublicKey
Public returns the same value as PubKey, but complies with crypto.Signer interface
func (PrivateKey) Serialize ¶
func (p PrivateKey) Serialize() []byte
Serialize returns the private key as a 256-bit big-endian binary-encoded number, padded to a length of 32 bytes.
func (*PrivateKey) Sign ¶ added in v0.2.1
func (privkey *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error)
Sign will sign the provided digest, returning the resulting signature. SignOptions can be used to pass options. By default DER format will be used for signatures, however compact format can be specified via opts.
func (*PrivateKey) ToECDSA ¶
func (p *PrivateKey) ToECDSA() *ecdsa.PrivateKey
ToECDSA returns the private key as a *ecdsa.PrivateKey.
func (*PrivateKey) Zero ¶
func (p *PrivateKey) Zero()
Zero manually clears the memory associated with the private key. This can be used to explicitly clear key material from memory for enhanced security against memory scraping.
type PublicKey ¶
type PublicKey struct {
// contains filtered or unexported fields
}
PublicKey provides facilities for efficiently working with secp256k1 public keys within this package and includes functions to serialize in both uncompressed and compressed SEC (Standards for Efficient Cryptography) formats.
func NewPublicKey ¶
NewPublicKey instantiates a new public key with the given x and y coordinates.
It should be noted that, unlike ParsePubKey, since this accepts arbitrary x and y coordinates, it allows creation of public keys that are not valid points on the secp256k1 curve. The IsOnCurve method of the returned instance can be used to determine validity.
func ParsePubKey ¶
ParsePubKey parses a secp256k1 public key encoded according to the format specified by ANSI X9.62-1998, which means it is also compatible with the SEC (Standards for Efficient Cryptography) specification which is a subset of the former. In other words, it supports the uncompressed, compressed, and hybrid formats as follows:
Compressed:
<format byte = 0x02/0x03><32-byte X coordinate>
Uncompressed:
<format byte = 0x04><32-byte X coordinate><32-byte Y coordinate>
Hybrid:
<format byte = 0x05/0x06><32-byte X coordinate><32-byte Y coordinate>
NOTE: The hybrid format makes little sense in practice an therefore this package will not produce public keys serialized in this format. However, this function will properly parse them since they exist in the wild.
func RecoverCompact
deprecated
added in
v0.2.0
RecoverCompact attempts to recover the secp256k1 public key from the provided compact signature and message hash. It first verifies the signature, and, if the signature matches then the recovered public key will be returned as well as a boolean indicating whether or not the original key was compressed.
Deprecated: use Signature.RecoverPublicKey instead
func (*PublicKey) AsJacobian ¶
func (p *PublicKey) AsJacobian(result *JacobianPoint)
AsJacobian converts the public key into a Jacobian point with Z=1 and stores the result in the provided result param. This allows the public key to be treated a Jacobian point in the secp256k1 group in calculations.
func (*PublicKey) IsEqual ¶
IsEqual compares this public key instance to the one passed, returning true if both public keys are equivalent. A public key is equivalent to another, if they both have the same X and Y coordinates.
func (*PublicKey) IsOnCurve ¶
IsOnCurve returns whether or not the public key represents a point on the secp256k1 curve.
func (PublicKey) SerializeCompressed ¶
SerializeCompressed serializes a public key in the 33-byte compressed format.
func (PublicKey) SerializeUncompressed ¶
SerializeUncompressed serializes a public key in the 65-byte uncompressed format.
type SignOptions ¶ added in v0.2.1
type SignOptions struct { Format SignatureFormat Hash crypto.Hash }
func (*SignOptions) HashFunc ¶ added in v0.2.1
func (s *SignOptions) HashFunc() crypto.Hash
type Signature ¶ added in v0.2.0
type Signature struct {
// contains filtered or unexported fields
}
Signature is a type representing an ECDSA signature.
func NewSignature ¶ added in v0.2.0
func NewSignature(r, s *ModNScalar) *Signature
NewSignature instantiates a new signature given some r and s values.
func NewSignatureWithRecoveryCode ¶ added in v0.2.3
func NewSignatureWithRecoveryCode(r, s *ModNScalar, v byte) *Signature
NewSignatureWithRecoveryCode instantiates a new signature given some r and s values and a recovery code.
func ParseCompactSignature ¶ added in v0.2.7
func ParseDERSignature ¶ added in v0.2.0
ParseDERSignature parses a signature in the Distinguished Encoding Rules (DER) format per section 10 of [ISO/IEC 8825-1] and enforces the following additional restrictions specific to secp256k1:
- The R and S values must be in the valid range for secp256k1 scalars:
- Negative values are rejected
- Zero is rejected
- Values greater than or equal to the secp256k1 group order are rejected
func Sign ¶ added in v0.2.0
func Sign(key *PrivateKey, hash []byte) *Signature
Sign generates an ECDSA signature over the secp256k1 curve for the provided hash (which should be the result of hashing a larger message) using the given private key. The produced signature is deterministic (same message and same key yield the same signature) and canonical in accordance with RFC6979 and BIP0062.
Example ¶
This example demonstrates signing a message with a secp256k1 private key that is first parsed from raw bytes and serializing the generated signature.
package main import ( "encoding/hex" "fmt" "github.com/ModChain/blake256" "github.com/ModChain/secp256k1" ) func main() { // Decode a hex-encoded private key. pkBytes, err := hex.DecodeString("22a47fa09a223f2aa079edf85a7c2d4f87" + "20ee63e502ee2869afab7de234b80c") if err != nil { fmt.Println(err) return } privKey := secp256k1.PrivKeyFromBytes(pkBytes) // Sign a message using the private key. message := "test message" messageHash := blake256.Sum256([]byte(message)) signature := secp256k1.Sign(privKey, messageHash[:]) // Serialize and display the signature. fmt.Printf("Serialized Signature: %x\n", signature.Serialize()) // Verify the signature for the message using the public key. pubKey := privKey.PubKey() verified := signature.Verify(messageHash[:], pubKey) fmt.Printf("Signature Verified? %v\n", verified) }
Output: Serialized Signature: 3045022100fcc0a8768cfbcefcf2cadd7cfb0fb18ed08dd2e2ae84bef1a474a3d351b26f0302200fc1a350b45f46fa00101391302818d748c2b22615511a3ffd5bb638bd777207 Signature Verified? true
func (*Signature) BruteforceRecoveryCode ¶ added in v0.2.3
BruteforceRecoveryCode will compute what the recovery code is based on the PublicKey and message rather than knowing what the code was. The process is very similar to Verify but doesn't go as far since we assume the signature is valid.
func (*Signature) ExportCompact ¶ added in v0.2.5
ExportCompact exports the signature in compact format
func (*Signature) IsEqual ¶ added in v0.2.0
IsEqual compares this Signature instance to the one passed, returning true if both Signatures are equivalent. A signature is equivalent to another, if they both have the same scalar value for R and S.
func (*Signature) R ¶ added in v0.2.0
func (sig *Signature) R() ModNScalar
R returns the r value of the signature.
func (*Signature) RecoverPublicKey ¶ added in v0.2.3
RecoverPublicKey recovers the public key
func (*Signature) RecoveryCode ¶ added in v0.2.3
RecoveryCode returns the recovery byte of the signature that can be used to determine the original signing public key.
func (*Signature) S ¶ added in v0.2.0
func (sig *Signature) S() ModNScalar
S returns the s value of the signature.
func (*Signature) Serialize ¶ added in v0.2.0
Serialize returns the ECDSA signature in the Distinguished Encoding Rules (DER) format per section 10 of [ISO/IEC 8825-1] and such that the S component of the signature is less than or equal to the half order of the group.
Note that the serialized bytes returned do not include the appended hash type used in Decred signature scripts.
func (*Signature) Verify ¶ added in v0.2.0
Verify returns whether or not the signature is valid for the provided hash and secp256k1 public key.
Example ¶
This example demonstrates verifying a secp256k1 signature against a public key that is first parsed from raw bytes. The signature is also parsed from raw bytes.
package main import ( "encoding/hex" "fmt" "github.com/ModChain/blake256" "github.com/ModChain/secp256k1" ) func main() { // Decode hex-encoded serialized public key. pubKeyBytes, err := hex.DecodeString("02a673638cb9587cb68ea08dbef685c" + "6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5") if err != nil { fmt.Println(err) return } pubKey, err := secp256k1.ParsePubKey(pubKeyBytes) if err != nil { fmt.Println(err) return } // Decode hex-encoded serialized signature. sigBytes, err := hex.DecodeString("3045022100fcc0a8768cfbcefcf2cadd7cfb0" + "fb18ed08dd2e2ae84bef1a474a3d351b26f0302200fc1a350b45f46fa0010139130" + "2818d748c2b22615511a3ffd5bb638bd777207") if err != nil { fmt.Println(err) return } signature, err := secp256k1.ParseDERSignature(sigBytes) if err != nil { fmt.Println(err) return } // Verify the signature for the message using the public key. message := "test message" messageHash := blake256.Sum256([]byte(message)) verified := signature.Verify(messageHash[:], pubKey) fmt.Println("Signature Verified?", verified) }
Output: Signature Verified? true
type SignatureFormat ¶ added in v0.2.2
type SignatureFormat uint
const ( SignFormatDER SignatureFormat = iota // DER format by default SignFormatCompact )