WIP secp256k1 support
This commit is contained in:
43
crypto/secp256k1/key.go
Normal file
43
crypto/secp256k1/key.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package secp256k1
|
||||
|
||||
import (
|
||||
"encoding/asn1"
|
||||
|
||||
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
||||
)
|
||||
|
||||
const (
|
||||
// PublicKeyBytesSize is the size, in bytes, of public keys in raw bytes.
|
||||
PublicKeyBytesSize = secp256k1.PubKeyBytesLenCompressed
|
||||
// PrivateKeyBytesSize is the size, in bytes, of private keys in raw bytes.
|
||||
PrivateKeyBytesSize = secp256k1.PrivKeyBytesLen
|
||||
// SignatureBytesSize is the size, in bytes, of signatures in raw bytes.
|
||||
SignatureBytesSize = 123456
|
||||
|
||||
MultibaseCode = uint64(0xe7)
|
||||
|
||||
// coordinateSize is the size, in bytes, of one coordinate in the elliptic curve.
|
||||
coordinateSize = 32
|
||||
)
|
||||
|
||||
func GenerateKeyPair() (*PublicKey, *PrivateKey, error) {
|
||||
priv, err := secp256k1.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pub := priv.PubKey()
|
||||
return &PublicKey{k: pub}, &PrivateKey{k: priv}, nil
|
||||
}
|
||||
|
||||
const (
|
||||
pemPubBlockType = "PUBLIC KEY"
|
||||
pemPrivBlockType = "PRIVATE KEY"
|
||||
)
|
||||
|
||||
var (
|
||||
// Elliptic curve public key (OID: 1.2.840.10045.2.1)
|
||||
oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
|
||||
|
||||
// Curve is secp256k1 (OID: 1.3.132.0.10)
|
||||
oidSecp256k1 = asn1.ObjectIdentifier{1, 3, 132, 0, 10}
|
||||
)
|
||||
82
crypto/secp256k1/key_test.go
Normal file
82
crypto/secp256k1/key_test.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package secp256k1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/INFURA/go-did/crypto"
|
||||
"github.com/INFURA/go-did/crypto/_testsuite"
|
||||
)
|
||||
|
||||
var harness = testsuite.TestHarness[*PublicKey, *PrivateKey]{
|
||||
Name: "secp256k1",
|
||||
GenerateKeyPair: GenerateKeyPair,
|
||||
PublicKeyFromBytes: PublicKeyFromBytes,
|
||||
PublicKeyFromPublicKeyMultibase: PublicKeyFromPublicKeyMultibase,
|
||||
PublicKeyFromX509DER: PublicKeyFromX509DER,
|
||||
PublicKeyFromX509PEM: PublicKeyFromX509PEM,
|
||||
PrivateKeyFromBytes: PrivateKeyFromBytes,
|
||||
PrivateKeyFromPKCS8DER: PrivateKeyFromPKCS8DER,
|
||||
PrivateKeyFromPKCS8PEM: PrivateKeyFromPKCS8PEM,
|
||||
MultibaseCode: MultibaseCode,
|
||||
DefaultHash: crypto.SHA256,
|
||||
OtherHashes: []crypto.Hash{crypto.KECCAK_256},
|
||||
PublicKeyBytesSize: PublicKeyBytesSize,
|
||||
PrivateKeyBytesSize: PrivateKeyBytesSize,
|
||||
SignatureBytesSize: SignatureBytesSize,
|
||||
}
|
||||
|
||||
func TestSuite(t *testing.T) {
|
||||
testsuite.TestSuite(t, harness)
|
||||
}
|
||||
|
||||
func BenchmarkSuite(b *testing.B) {
|
||||
testsuite.BenchSuite(b, harness)
|
||||
}
|
||||
|
||||
func TestPublicKeyX509(t *testing.T) {
|
||||
// openssl ecparam -genkey -name secp256k1 | openssl pkcs8 -topk8 -nocrypt -out secp256k1-key.pem
|
||||
// openssl pkey -in secp256k1-key.pem -pubout -out secp256k1-pubkey.pem
|
||||
pem := `-----BEGIN PUBLIC KEY-----
|
||||
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEFVP6HKjIReiiUgrC+t+FjG5u0PXIoBmN
|
||||
V1MMmoOFfKlrD/HuWUjjlw0mDKZcG7AM7JKPTWMOCcvUR2B8BUO3VQ==
|
||||
-----END PUBLIC KEY-----
|
||||
`
|
||||
|
||||
pub, err := PublicKeyFromX509PEM(pem)
|
||||
require.NoError(t, err)
|
||||
|
||||
rt := pub.ToX509PEM()
|
||||
require.Equal(t, pem, rt)
|
||||
}
|
||||
|
||||
func TestPrivateKeyPKCS8(t *testing.T) {
|
||||
// openssl ecparam -genkey -name secp256k1 | openssl pkcs8 -topk8 -nocrypt -out secp256k1-key.pem
|
||||
pem := `-----BEGIN PRIVATE KEY-----
|
||||
MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgZW9JcJ1kN+DW2IFgqKJu
|
||||
KS+39/xVa0n2J+lCr7hYGTihRANCAAQVU/ocqMhF6KJSCsL634WMbm7Q9cigGY1X
|
||||
Uwyag4V8qWsP8e5ZSOOXDSYMplwbsAzsko9NYw4Jy9RHYHwFQ7dV
|
||||
-----END PRIVATE KEY-----
|
||||
`
|
||||
|
||||
priv, err := PrivateKeyFromPKCS8PEM(pem)
|
||||
require.NoError(t, err)
|
||||
|
||||
rt := priv.ToPKCS8PEM()
|
||||
require.Equal(t, pem, rt)
|
||||
}
|
||||
|
||||
func FuzzPrivateKeyFromPKCS8PEM(f *testing.F) {
|
||||
f.Add(`-----BEGIN PRIVATE KEY-----
|
||||
MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgZW9JcJ1kN+DW2IFgqKJu
|
||||
KS+39/xVa0n2J+lCr7hYGTihRANCAAQVU/ocqMhF6KJSCsL634WMbm7Q9cigGY1X
|
||||
Uwyag4V8qWsP8e5ZSOOXDSYMplwbsAzsko9NYw4Jy9RHYHwFQ7dV
|
||||
-----END PRIVATE KEY-----
|
||||
`)
|
||||
|
||||
f.Fuzz(func(t *testing.T, data string) {
|
||||
// looking for panics
|
||||
_, _ = PrivateKeyFromPKCS8PEM(data)
|
||||
})
|
||||
}
|
||||
218
crypto/secp256k1/private.go
Normal file
218
crypto/secp256k1/private.go
Normal file
@@ -0,0 +1,218 @@
|
||||
package secp256k1
|
||||
|
||||
import (
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
|
||||
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
||||
"github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
|
||||
|
||||
"github.com/INFURA/go-did/crypto"
|
||||
)
|
||||
|
||||
var _ crypto.PrivateKeySigning = &PrivateKey{}
|
||||
var _ crypto.PrivateKeyKeyExchange = &PrivateKey{}
|
||||
|
||||
type PrivateKey struct {
|
||||
k *secp256k1.PrivateKey
|
||||
}
|
||||
|
||||
// PrivateKeyFromBytes converts a serialized public key to a PrivateKey.
|
||||
// This compact serialization format is the raw key material, without metadata or structure.
|
||||
// It errors if the slice is not the right size.
|
||||
func PrivateKeyFromBytes(b []byte) (*PrivateKey, error) {
|
||||
if len(b) != PrivateKeyBytesSize {
|
||||
return nil, fmt.Errorf("invalid secp256k1 private key size")
|
||||
}
|
||||
return &PrivateKey{k: secp256k1.PrivKeyFromBytes(b)}, nil
|
||||
}
|
||||
|
||||
// PrivateKeyFromPKCS8DER decodes a PKCS#8 DER (binary) encoded private key.
|
||||
func PrivateKeyFromPKCS8DER(bytes []byte) (*PrivateKey, error) {
|
||||
// Parse the PKCS#8 structure
|
||||
var pkcs8 struct {
|
||||
Version int
|
||||
Algo pkix.AlgorithmIdentifier
|
||||
PrivateKey []byte
|
||||
}
|
||||
if _, err := asn1.Unmarshal(bytes, &pkcs8); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse PKCS#8 structure: %w", err)
|
||||
}
|
||||
|
||||
// Check if this is an Elliptic curve public key (OID: 1.2.840.10045.2.1)
|
||||
if !pkcs8.Algo.Algorithm.Equal(oidPublicKeyECDSA) {
|
||||
return nil, fmt.Errorf("not an EC private key, got OID: %v", pkcs8.Algo.Algorithm)
|
||||
}
|
||||
|
||||
// Extract the curve OID from parameters
|
||||
var namedCurveOID asn1.ObjectIdentifier
|
||||
if _, err := asn1.Unmarshal(pkcs8.Algo.Parameters.FullBytes, &namedCurveOID); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse curve parameters: %w", err)
|
||||
}
|
||||
|
||||
// Check if the curve is secp256k1 (OID: 1.3.132.0.10)
|
||||
if !namedCurveOID.Equal(oidSecp256k1) {
|
||||
return nil, fmt.Errorf("unsupported curve, expected secp256k1 (1.3.132.0.10), got: %v", namedCurveOID)
|
||||
}
|
||||
|
||||
// Parse the EC private key structure (RFC 5915)
|
||||
var ecPrivKey struct {
|
||||
Version int
|
||||
PrivateKey []byte
|
||||
PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"`
|
||||
}
|
||||
|
||||
if _, err := asn1.Unmarshal(pkcs8.PrivateKey, &ecPrivKey); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse alliptic curve private key: %w", err)
|
||||
}
|
||||
|
||||
// Validate the EC private key version
|
||||
if ecPrivKey.Version != 1 {
|
||||
return nil, fmt.Errorf("unsupported EC private key version: %d", ecPrivKey.Version)
|
||||
}
|
||||
|
||||
// Validate private key length
|
||||
if len(ecPrivKey.PrivateKey) != PrivateKeyBytesSize {
|
||||
return nil, fmt.Errorf("invalid secp256k1 private key length: %d, expected %d", len(ecPrivKey.PrivateKey), PrivateKeyBytesSize)
|
||||
}
|
||||
|
||||
// Create the secp256k1 private key
|
||||
privKeySecp256k1 := secp256k1.PrivKeyFromBytes(ecPrivKey.PrivateKey)
|
||||
|
||||
return &PrivateKey{k: privKeySecp256k1}, nil
|
||||
}
|
||||
|
||||
// PrivateKeyFromPKCS8PEM decodes an PKCS#8 PEM (string) encoded private key.
|
||||
func PrivateKeyFromPKCS8PEM(str string) (*PrivateKey, error) {
|
||||
block, _ := pem.Decode([]byte(str))
|
||||
if block == nil {
|
||||
return nil, fmt.Errorf("failed to decode PEM block")
|
||||
}
|
||||
if block.Type != pemPrivBlockType {
|
||||
return nil, fmt.Errorf("incorrect PEM block type")
|
||||
}
|
||||
return PrivateKeyFromPKCS8DER(block.Bytes)
|
||||
}
|
||||
|
||||
func (p *PrivateKey) Equal(other crypto.PrivateKey) bool {
|
||||
if other, ok := other.(*PrivateKey); ok {
|
||||
return p.k.PubKey().IsEqual(other.k.PubKey())
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *PrivateKey) Public() crypto.PublicKey {
|
||||
return &PublicKey{k: p.k.PubKey()}
|
||||
}
|
||||
|
||||
func (p *PrivateKey) ToBytes() []byte {
|
||||
return p.k.Serialize()
|
||||
}
|
||||
|
||||
func (p *PrivateKey) ToPKCS8DER() []byte {
|
||||
pubkeyBytes := p.k.PubKey().SerializeUncompressed()
|
||||
|
||||
// Create the EC private key structure
|
||||
// This follows RFC 5915 format for EC private keys
|
||||
ecPrivateKey := struct {
|
||||
Version int
|
||||
PrivateKey []byte
|
||||
Parameters asn1.RawValue `asn1:"optional,explicit,tag:0"`
|
||||
PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"`
|
||||
}{
|
||||
Version: 1,
|
||||
PrivateKey: p.k.Serialize(),
|
||||
// Parameters are omitted since they're specified in the algorithm identifier
|
||||
|
||||
// Pubkey could be omitted, but we include it to match openssl behavior
|
||||
PublicKey: asn1.BitString{
|
||||
Bytes: pubkeyBytes,
|
||||
BitLength: 8 * len(pubkeyBytes),
|
||||
},
|
||||
}
|
||||
|
||||
ecPrivKeyDER, err := asn1.Marshal(ecPrivateKey)
|
||||
if err != nil {
|
||||
panic(err) // This should not happen with valid key data
|
||||
}
|
||||
|
||||
// Create the PKCS#8 structure
|
||||
pkcs8 := struct {
|
||||
Version int
|
||||
Algo pkix.AlgorithmIdentifier
|
||||
PrivateKey []byte
|
||||
}{
|
||||
Version: 0,
|
||||
Algo: pkix.AlgorithmIdentifier{
|
||||
// Elliptic curve public key (OID: 1.2.840.10045.2.1)
|
||||
Algorithm: oidPublicKeyECDSA,
|
||||
Parameters: asn1.RawValue{
|
||||
FullBytes: must(asn1.Marshal(oidSecp256k1)),
|
||||
},
|
||||
},
|
||||
PrivateKey: ecPrivKeyDER,
|
||||
}
|
||||
|
||||
der, err := asn1.Marshal(pkcs8)
|
||||
if err != nil {
|
||||
panic(err) // This should not happen with valid key data
|
||||
}
|
||||
|
||||
return der
|
||||
}
|
||||
|
||||
func (p *PrivateKey) ToPKCS8PEM() string {
|
||||
der := p.ToPKCS8DER()
|
||||
return string(pem.EncodeToMemory(&pem.Block{
|
||||
Type: pemPrivBlockType,
|
||||
Bytes: der,
|
||||
}))
|
||||
}
|
||||
|
||||
// The default signing hash is SHA-256.
|
||||
func (p *PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
hasher := params.HashOrDefault(crypto.SHA256).New()
|
||||
hasher.Write(message)
|
||||
hash := hasher.Sum(nil)
|
||||
|
||||
// TODO
|
||||
return ecdsa.SignCompact(p.k, hash[:], false), nil
|
||||
}
|
||||
|
||||
// The default signing hash is SHA-256.
|
||||
func (p *PrivateKey) SignToASN1(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||
// // Hash the message with SHA-256
|
||||
// hash := sha256.Sum256(message)
|
||||
//
|
||||
// return ecdsa.SignASN1(rand.Reader, p.k.ToECDSA(), hash[:])
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (p *PrivateKey) PublicKeyIsCompatible(remote crypto.PublicKey) bool {
|
||||
if _, ok := remote.(*PublicKey); ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *PrivateKey) KeyExchange(remote crypto.PublicKey) ([]byte, error) {
|
||||
// if remote, ok := remote.(*PublicKey); ok {
|
||||
// // First, we need to convert the ECDSA (signing only) to the equivalent ECDH keys
|
||||
// ecdhPriv, err := p.k.ECDH()
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// ecdhPub, err := remote.k.ECDH()
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// return ecdhPriv.ECDH(ecdhPub)
|
||||
// }
|
||||
// return nil, fmt.Errorf("incompatible public key")
|
||||
panic("not implemented")
|
||||
}
|
||||
203
crypto/secp256k1/public.go
Normal file
203
crypto/secp256k1/public.go
Normal file
@@ -0,0 +1,203 @@
|
||||
package secp256k1
|
||||
|
||||
import (
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
|
||||
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
||||
|
||||
"github.com/INFURA/go-did/crypto"
|
||||
helpers "github.com/INFURA/go-did/crypto/internal"
|
||||
)
|
||||
|
||||
var _ crypto.PublicKeySigning = &PublicKey{}
|
||||
|
||||
type PublicKey struct {
|
||||
k *secp256k1.PublicKey
|
||||
}
|
||||
|
||||
// PublicKeyFromBytes converts a serialized public key to a PublicKey.
|
||||
// This compact serialization format is the raw key material, without metadata or structure.
|
||||
// It errors if the slice is not the right size.
|
||||
func PublicKeyFromBytes(b []byte) (*PublicKey, error) {
|
||||
pub, err := secp256k1.ParsePubKey(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &PublicKey{k: pub}, nil
|
||||
}
|
||||
|
||||
// PublicKeyFromXY converts x and y coordinates into a PublicKey.
|
||||
func PublicKeyFromXY(x, y []byte) (*PublicKey, error) {
|
||||
var xf, yf secp256k1.FieldVal
|
||||
if xf.SetByteSlice(x) {
|
||||
return nil, fmt.Errorf("invalid secp255k1 public key")
|
||||
}
|
||||
if yf.SetByteSlice(y) {
|
||||
return nil, fmt.Errorf("invalid secp255k1 public key")
|
||||
}
|
||||
return &PublicKey{k: secp256k1.NewPublicKey(&xf, &yf)}, nil
|
||||
}
|
||||
|
||||
// PublicKeyFromPublicKeyMultibase decodes the public key from its Multibase form
|
||||
func PublicKeyFromPublicKeyMultibase(multibase string) (*PublicKey, error) {
|
||||
code, bytes, err := helpers.PublicKeyMultibaseDecode(multibase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if code != MultibaseCode {
|
||||
return nil, fmt.Errorf("invalid code")
|
||||
}
|
||||
return PublicKeyFromBytes(bytes)
|
||||
}
|
||||
|
||||
// PublicKeyFromX509DER decodes an X.509 DER (binary) encoded public key.
|
||||
func PublicKeyFromX509DER(bytes []byte) (*PublicKey, error) {
|
||||
// Parse the X.509 SubjectPublicKeyInfo structure
|
||||
var spki struct {
|
||||
Algorithm pkix.AlgorithmIdentifier
|
||||
SubjectPublicKey asn1.BitString
|
||||
}
|
||||
|
||||
if _, err := asn1.Unmarshal(bytes, &spki); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse X.509 SubjectPublicKeyInfo: %w", err)
|
||||
}
|
||||
|
||||
// Check if this is an Elliptic curve public key (OID: 1.2.840.10045.2.1)
|
||||
if !spki.Algorithm.Algorithm.Equal(oidPublicKeyECDSA) {
|
||||
return nil, fmt.Errorf("not an Elliptic curve public key, got OID: %v", spki.Algorithm.Algorithm)
|
||||
}
|
||||
|
||||
// Extract the curve OID from parameters
|
||||
var namedCurveOID asn1.ObjectIdentifier
|
||||
if _, err := asn1.Unmarshal(spki.Algorithm.Parameters.FullBytes, &namedCurveOID); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse curve parameters: %w", err)
|
||||
}
|
||||
// Check if this is secp256k1 (OID: 1.3.132.0.10)
|
||||
if !namedCurveOID.Equal(oidSecp256k1) {
|
||||
return nil, fmt.Errorf("unsupported curve, expected secp256k1 (1.3.132.0.10), got: %v", namedCurveOID)
|
||||
}
|
||||
|
||||
pubKey, err := secp256k1.ParsePubKey(spki.SubjectPublicKey.Bytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse secp256k1 public key: %w", err)
|
||||
}
|
||||
|
||||
return &PublicKey{k: pubKey}, nil
|
||||
}
|
||||
|
||||
// PublicKeyFromX509PEM decodes an X.509 PEM (string) encoded public key.
|
||||
func PublicKeyFromX509PEM(str string) (*PublicKey, error) {
|
||||
block, _ := pem.Decode([]byte(str))
|
||||
if block == nil {
|
||||
return nil, fmt.Errorf("failed to decode PEM block")
|
||||
}
|
||||
if block.Type != pemPubBlockType {
|
||||
return nil, fmt.Errorf("incorrect PEM block type")
|
||||
}
|
||||
return PublicKeyFromX509DER(block.Bytes)
|
||||
}
|
||||
|
||||
func (p *PublicKey) XBytes() []byte {
|
||||
// fixed size buffer that can get allocated on the caller's stack after inlining.
|
||||
var buf [coordinateSize]byte
|
||||
p.k.X().FillBytes(buf[:])
|
||||
return buf[:]
|
||||
}
|
||||
|
||||
func (p *PublicKey) YBytes() []byte {
|
||||
// fixed size buffer that can get allocated on the caller's stack after inlining.
|
||||
var buf [coordinateSize]byte
|
||||
p.k.Y().FillBytes(buf[:])
|
||||
return buf[:]
|
||||
}
|
||||
|
||||
func (p *PublicKey) Equal(other crypto.PublicKey) bool {
|
||||
if other, ok := other.(*PublicKey); ok {
|
||||
return p.k.IsEqual(other.k)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *PublicKey) ToBytes() []byte {
|
||||
// 33-byte compressed format
|
||||
return p.k.SerializeCompressed()
|
||||
}
|
||||
|
||||
func (p *PublicKey) ToPublicKeyMultibase() string {
|
||||
return helpers.PublicKeyMultibaseEncode(MultibaseCode, p.k.SerializeCompressed())
|
||||
}
|
||||
|
||||
func (p *PublicKey) ToX509DER() []byte {
|
||||
pubKeyBytes := p.k.SerializeUncompressed()
|
||||
|
||||
// Create the X.509 SubjectPublicKeyInfo structure
|
||||
spki := struct {
|
||||
Algorithm pkix.AlgorithmIdentifier
|
||||
SubjectPublicKey asn1.BitString
|
||||
}{
|
||||
Algorithm: pkix.AlgorithmIdentifier{
|
||||
Algorithm: oidPublicKeyECDSA,
|
||||
Parameters: asn1.RawValue{
|
||||
FullBytes: must(asn1.Marshal(oidSecp256k1)),
|
||||
},
|
||||
},
|
||||
SubjectPublicKey: asn1.BitString{
|
||||
Bytes: pubKeyBytes,
|
||||
BitLength: len(pubKeyBytes) * 8,
|
||||
},
|
||||
}
|
||||
|
||||
der, err := asn1.Marshal(spki)
|
||||
if err != nil {
|
||||
panic(err) // This should not happen with valid key data
|
||||
}
|
||||
|
||||
return der
|
||||
}
|
||||
|
||||
func (p *PublicKey) ToX509PEM() string {
|
||||
der := p.ToX509DER()
|
||||
return string(pem.EncodeToMemory(&pem.Block{
|
||||
Type: pemPubBlockType,
|
||||
Bytes: der,
|
||||
}))
|
||||
}
|
||||
|
||||
/*
|
||||
Note: signatures for the crypto.PrivateKeySigning interface assumes SHA256,
|
||||
which should be correct almost always. If there is a need to use a different
|
||||
hash function, we can add separate functions that have that flexibility.
|
||||
*/
|
||||
|
||||
func (p *PublicKey) VerifyBytes(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||
// if len(signature) != SignatureBytesSize {
|
||||
// return false
|
||||
// }
|
||||
//
|
||||
// // Hash the message with SHA-256
|
||||
// hash := sha256.Sum256(message)
|
||||
//
|
||||
// r := new(big.Int).SetBytes(signature[:SignatureBytesSize/2])
|
||||
// s := new(big.Int).SetBytes(signature[SignatureBytesSize/2:])
|
||||
//
|
||||
// return ecdsa.Verify(p.k, hash[:], r, s)
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (p *PublicKey) VerifyASN1(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||
// // Hash the message with SHA-256
|
||||
// hash := sha256.Sum256(message)
|
||||
//
|
||||
// return ecdsa.VerifyASN1(p.k, hash[:], signature)
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func must[T any](v T, err error) T {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
Reference in New Issue
Block a user