"bytes", PKCS8/X509 x DER/PEM serialization for every keys

This commit is contained in:
Michael Muré
2025-06-18 19:04:17 +02:00
parent e15cc2295a
commit 4bfdc4bf2e
7 changed files with 400 additions and 14 deletions

View File

@@ -29,7 +29,7 @@ func TestJsonRoundTrip(t *testing.T) {
require.JSONEq(t, data, string(bytes)) require.JSONEq(t, data, string(bytes))
} }
func TestSignature(t *testing.T) { func TestVerify(t *testing.T) {
// test vector from https://datatracker.ietf.org/doc/html/rfc8032#section-7.1 // test vector from https://datatracker.ietf.org/doc/html/rfc8032#section-7.1
pkHex := "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025" pkHex := "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025"

View File

@@ -3,6 +3,8 @@ package ed25519
import ( import (
"crypto/ed25519" "crypto/ed25519"
"crypto/rand" "crypto/rand"
"crypto/x509"
"encoding/pem"
"fmt" "fmt"
"github.com/INFURA/go-did/verifications/internal" "github.com/INFURA/go-did/verifications/internal"
@@ -27,6 +29,7 @@ func GenerateKeyPair() (PublicKey, PrivateKey, error) {
} }
// PublicKeyFromBytes converts a serialized public key to a 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. // It errors if the slice is not the right size.
func PublicKeyFromBytes(b []byte) (PublicKey, error) { func PublicKeyFromBytes(b []byte) (PublicKey, error) {
if len(b) != PublicKeySize { if len(b) != PublicKeySize {
@@ -37,6 +40,7 @@ func PublicKeyFromBytes(b []byte) (PublicKey, error) {
} }
// PublicKeyToBytes converts a public key to a byte slice. // PublicKeyToBytes converts a public key to a byte slice.
// This compact serialization format is the raw key material, without metadata or structure.
func PublicKeyToBytes(pub PublicKey) []byte { func PublicKeyToBytes(pub PublicKey) []byte {
// Copy the private key to a fixed size buffer that can get allocated on the // Copy the private key to a fixed size buffer that can get allocated on the
// caller's stack after inlining. // caller's stack after inlining.
@@ -64,7 +68,46 @@ func PublicKeyToMultibase(pub PublicKey) string {
return helpers.MultibaseEncode(MultibaseCode, pub) return helpers.MultibaseEncode(MultibaseCode, pub)
} }
// PublicKeyFromX509DER decodes an X.509 DER (binary) encoded public key.
func PublicKeyFromX509DER(bytes []byte) (PublicKey, error) {
pub, err := x509.ParsePKIXPublicKey(bytes)
if err != nil {
return nil, err
}
return pub.(PublicKey), nil
}
// PublicKeyToX509DER encodes the public key into the X.509 DER (binary) format.
func PublicKeyToX509DER(pub PublicKey) []byte {
res, _ := x509.MarshalPKIXPublicKey(pub)
return res
}
const pemPubBlockType = "PUBLIC KEY"
// 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)
}
// PublicKeyToX509PEM encodes the public key into the X.509 PEM (binary) format.
func PublicKeyToX509PEM(pub PublicKey) string {
der := PublicKeyToX509DER(pub)
return string(pem.EncodeToMemory(&pem.Block{
Type: pemPubBlockType,
Bytes: der,
}))
}
// PrivateKeyFromBytes converts a serialized private key to a PrivateKey. // PrivateKeyFromBytes converts a serialized private 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. // It errors if the slice is not the right size.
func PrivateKeyFromBytes(b []byte) (PrivateKey, error) { func PrivateKeyFromBytes(b []byte) (PrivateKey, error) {
if len(b) != PrivateKeySize { if len(b) != PrivateKeySize {
@@ -75,6 +118,7 @@ func PrivateKeyFromBytes(b []byte) (PrivateKey, error) {
} }
// PrivateKeyToBytes converts a private key to a byte slice. // PrivateKeyToBytes converts a private key to a byte slice.
// This compact serialization format is the raw key material, without metadata or structure.
func PrivateKeyToBytes(priv PrivateKey) []byte { func PrivateKeyToBytes(priv PrivateKey) []byte {
// Copy the private key to a fixed size buffer that can get allocated on the // Copy the private key to a fixed size buffer that can get allocated on the
// caller's stack after inlining. // caller's stack after inlining.
@@ -82,6 +126,44 @@ func PrivateKeyToBytes(priv PrivateKey) []byte {
return append(buf[:0], priv...) return append(buf[:0], priv...)
} }
// PrivateKeyFromPKCS8DER decodes a PKCS#8 DER (binary) encoded private key.
func PrivateKeyFromPKCS8DER(bytes []byte) (PrivateKey, error) {
priv, err := x509.ParsePKCS8PrivateKey(bytes)
if err != nil {
return nil, err
}
return priv.(PrivateKey), nil
}
// PrivateKeyToPKCS8DER encodes the private key into the PKCS#8 DER (binary) format.
func PrivateKeyToPKCS8DER(priv PrivateKey) []byte {
res, _ := x509.MarshalPKCS8PrivateKey(priv)
return res
}
const pemPrivBlockType = "PRIVATE KEY"
// 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)
}
// PrivateKeyToPKCS8PEM encodes the private key into the PKCS#8 PEM (binary) format.
func PrivateKeyToPKCS8PEM(priv PrivateKey) string {
der := PrivateKeyToPKCS8DER(priv)
return string(pem.EncodeToMemory(&pem.Block{
Type: pemPrivBlockType,
Bytes: der,
}))
}
// Sign signs the message with privateKey and returns a signature. // Sign signs the message with privateKey and returns a signature.
// It will panic if len(privateKey) is not [PrivateKeySize]. // It will panic if len(privateKey) is not [PrivateKeySize].
func Sign(privateKey PrivateKey, message []byte) []byte { func Sign(privateKey PrivateKey, message []byte) []byte {

View File

@@ -1,6 +1,7 @@
package ed25519_test package ed25519_test
import ( import (
"fmt"
"testing" "testing"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@@ -21,11 +22,13 @@ func TestBytesRoundTrip(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
bytes := ed25519.PublicKeyToBytes(pub) bytes := ed25519.PublicKeyToBytes(pub)
fmt.Println("pub", len(bytes))
rtPub, err := ed25519.PublicKeyFromBytes(bytes) rtPub, err := ed25519.PublicKeyFromBytes(bytes)
require.NoError(t, err) require.NoError(t, err)
require.True(t, pub.Equal(rtPub)) require.True(t, pub.Equal(rtPub))
bytes = ed25519.PrivateKeyToBytes(priv) bytes = ed25519.PrivateKeyToBytes(priv)
fmt.Println("priv", len(bytes))
rtPriv, err := ed25519.PrivateKeyFromBytes(bytes) rtPriv, err := ed25519.PrivateKeyFromBytes(bytes)
require.NoError(t, err) require.NoError(t, err)
require.True(t, priv.Equal(rtPriv)) require.True(t, priv.Equal(rtPriv))
@@ -40,3 +43,47 @@ func TestMultibaseRoundTrip(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, pub, rt) require.Equal(t, pub, rt)
} }
func TestPublicKeyX509RoundTrip(t *testing.T) {
pub, _, err := ed25519.GenerateKeyPair()
require.NoError(t, err)
der := ed25519.PublicKeyToX509DER(pub)
fmt.Println("der", len(der))
rt, err := ed25519.PublicKeyFromX509DER(der)
require.NoError(t, err)
require.True(t, pub.Equal(rt))
pem := ed25519.PublicKeyToX509PEM(pub)
fmt.Println("pem", len(pem))
rt, err = ed25519.PublicKeyFromX509PEM(pem)
require.NoError(t, err)
require.True(t, pub.Equal(rt))
}
func TestPrivateKeyPKCS8RoundTrip(t *testing.T) {
pub, priv, err := ed25519.GenerateKeyPair()
require.NoError(t, err)
der := ed25519.PrivateKeyToPKCS8DER(priv)
fmt.Println("der", len(der))
rt, err := ed25519.PrivateKeyFromPKCS8DER(der)
require.NoError(t, err)
require.True(t, priv.Equal(rt))
require.True(t, pub.Equal(rt.Public()))
pem := ed25519.PrivateKeyToPKCS8PEM(priv)
fmt.Println("pem", len(pem))
rt, err = ed25519.PrivateKeyFromPKCS8PEM(pem)
require.NoError(t, err)
require.True(t, priv.Equal(rt))
require.True(t, pub.Equal(rt.Public()))
}
// func TestSignature(t *testing.T) {
// pub, priv, err := ed25519.GenerateKeyPair()
// require.NoError(t, err)
//
// sig := ed25519.Sign(priv, []byte("message"))
//
// }

View File

@@ -5,7 +5,9 @@ import (
"crypto/elliptic" "crypto/elliptic"
"crypto/rand" "crypto/rand"
"crypto/x509" "crypto/x509"
"encoding/pem"
"fmt" "fmt"
"math/big"
helpers "github.com/INFURA/go-did/verifications/internal" helpers "github.com/INFURA/go-did/verifications/internal"
) )
@@ -15,8 +17,8 @@ type PrivateKey = *ecdsa.PrivateKey
const ( const (
// TODO // TODO
PublicKeySize = 123456 PublicKeySize = 33
PrivateKeySize = 123456 PrivateKeySize = 32
SignatureSize = 123456 SignatureSize = 123456
MultibaseCode = uint64(0x1200) MultibaseCode = uint64(0x1200)
@@ -31,6 +33,7 @@ func GenerateKeyPair() (PublicKey, PrivateKey, error) {
} }
// PublicKeyFromBytes converts a serialized public key to a 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. // It errors if the slice is not the right size.
func PublicKeyFromBytes(b []byte) (PublicKey, error) { func PublicKeyFromBytes(b []byte) (PublicKey, error) {
if len(b) != PublicKeySize { if len(b) != PublicKeySize {
@@ -41,17 +44,25 @@ func PublicKeyFromBytes(b []byte) (PublicKey, error) {
return nil, fmt.Errorf("invalid P-256 public key") return nil, fmt.Errorf("invalid P-256 public key")
} }
return &ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}, nil return &ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}, nil
// if len(b) != PublicKeySize {
// return nil, fmt.Errorf("invalid P-256 public key size")
// }
// x := new(big.Int).SetBytes(b[:PublicKeySize/2])
// y := new(big.Int).SetBytes(b[PublicKeySize/2:])
// return &ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}, nil
} }
// PublicKeyToBytes converts a public key to a byte slice. // PublicKeyToBytes converts a public key to a byte slice.
func PublicKeyToBytes(pub PublicKey) (res []byte, err error) { // This compact serialization format is the raw key material, without metadata or structure.
defer func() { func PublicKeyToBytes(pub PublicKey) []byte {
if rerr := recover(); rerr != nil { return elliptic.MarshalCompressed(elliptic.P256(), pub.X, pub.Y)
err = fmt.Errorf("recovered panic: %s", rerr)
res = nil // // fixed size buffer that can get allocated on the caller's stack after inlining.
} // var buf [PublicKeySize]byte
}() // pub.X.FillBytes(buf[:PublicKeySize/2])
return x509.MarshalPKIXPublicKey(pub) // pub.Y.FillBytes(buf[PublicKeySize/2:])
// return buf[:]
} }
// PublicKeyFromMultibase decodes the public key from its Multibase form // PublicKeyFromMultibase decodes the public key from its Multibase form
@@ -72,13 +83,106 @@ func PublicKeyToMultibase(pub PublicKey) string {
return helpers.MultibaseEncode(MultibaseCode, bytes) return helpers.MultibaseEncode(MultibaseCode, bytes)
} }
// PublicKeyFromX509DER decodes an X.509 DER (binary) encoded public key.
func PublicKeyFromX509DER(bytes []byte) (PublicKey, error) {
pub, err := x509.ParsePKIXPublicKey(bytes)
if err != nil {
return nil, err
}
return pub.(PublicKey), nil
}
// PublicKeyToX509DER encodes the public key into the X.509 DER (binary) format.
func PublicKeyToX509DER(pub PublicKey) []byte {
res, _ := x509.MarshalPKIXPublicKey(pub)
return res
}
const pemPubBlockType = "PUBLIC KEY"
// 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)
}
// PublicKeyToX509PEM encodes the public key into the X.509 PEM (binary) format.
func PublicKeyToX509PEM(pub PublicKey) string {
der := PublicKeyToX509DER(pub)
return string(pem.EncodeToMemory(&pem.Block{
Type: pemPubBlockType,
Bytes: der,
}))
}
// PrivateKeyFromBytes converts a serialized public key to a 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. // It errors if the slice is not the right size.
func PrivateKeyFromBytes(b []byte) (PrivateKey, error) { func PrivateKeyFromBytes(b []byte) (PrivateKey, error) {
if len(b) != PrivateKeySize { if len(b) != PrivateKeySize {
return nil, fmt.Errorf("invalid P-256 private key size") return nil, fmt.Errorf("invalid P-256 private key size")
} }
// TODO
return nil, nil res := &ecdsa.PrivateKey{
D: new(big.Int).SetBytes(b),
PublicKey: ecdsa.PublicKey{Curve: elliptic.P256()},
}
// recompute the public key
res.PublicKey.X, res.PublicKey.Y = res.PublicKey.Curve.ScalarBaseMult(b)
return res, nil
}
// PrivateKeyToBytes converts a private key to a byte slice.
// This compact serialization format is the raw key material, without metadata or structure.
func PrivateKeyToBytes(priv PrivateKey) []byte {
// fixed size buffer that can get allocated on the caller's stack after inlining.
var buf [PrivateKeySize]byte
priv.D.FillBytes(buf[:])
return buf[:]
}
// PrivateKeyFromPKCS8DER decodes a PKCS#8 DER (binary) encoded private key.
func PrivateKeyFromPKCS8DER(bytes []byte) (PrivateKey, error) {
priv, err := x509.ParsePKCS8PrivateKey(bytes)
if err != nil {
return nil, err
}
return priv.(PrivateKey), nil
}
// PrivateKeyToPKCS8DER encodes the private key into the PKCS#8 DER (binary) format.
func PrivateKeyToPKCS8DER(priv PrivateKey) []byte {
res, _ := x509.MarshalPKCS8PrivateKey(priv)
return res
}
const pemPrivBlockType = "PRIVATE KEY"
// 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)
}
// PrivateKeyToPKCS8PEM encodes the private key into the PKCS#8 PEM (binary) format.
func PrivateKeyToPKCS8PEM(priv PrivateKey) string {
der := PrivateKeyToPKCS8DER(priv)
return string(pem.EncodeToMemory(&pem.Block{
Type: pemPrivBlockType,
Bytes: der,
}))
} }

View File

@@ -5,7 +5,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/INFURA/go-did/verifications/ed25519"
"github.com/INFURA/go-did/verifications/p256" "github.com/INFURA/go-did/verifications/p256"
) )
@@ -32,6 +31,38 @@ func TestBytesRoundTrip(t *testing.T) {
require.True(t, priv.Equal(rtPriv)) require.True(t, priv.Equal(rtPriv))
} }
func TestPublicKeyX509RoundTrip(t *testing.T) {
pub, _, err := p256.GenerateKeyPair()
require.NoError(t, err)
der := p256.PublicKeyToX509DER(pub)
rt, err := p256.PublicKeyFromX509DER(der)
require.NoError(t, err)
require.True(t, pub.Equal(rt))
pem := p256.PublicKeyToX509PEM(pub)
rt, err = p256.PublicKeyFromX509PEM(pem)
require.NoError(t, err)
require.True(t, pub.Equal(rt))
}
func TestPrivateKeyPKCS8RoundTrip(t *testing.T) {
pub, priv, err := p256.GenerateKeyPair()
require.NoError(t, err)
der := p256.PrivateKeyToPKCS8DER(priv)
rt, err := p256.PrivateKeyFromPKCS8DER(der)
require.NoError(t, err)
require.True(t, priv.Equal(rt))
require.True(t, pub.Equal(rt.Public()))
pem := p256.PrivateKeyToPKCS8PEM(priv)
rt, err = p256.PrivateKeyFromPKCS8PEM(pem)
require.NoError(t, err)
require.True(t, priv.Equal(rt))
require.True(t, pub.Equal(rt.Public()))
}
func TestMultibaseRoundTrip(t *testing.T) { func TestMultibaseRoundTrip(t *testing.T) {
pub, _, err := p256.GenerateKeyPair() pub, _, err := p256.GenerateKeyPair()
require.NoError(t, err) require.NoError(t, err)

View File

@@ -4,6 +4,8 @@ import (
"crypto/ecdh" "crypto/ecdh"
"crypto/rand" "crypto/rand"
"crypto/sha512" "crypto/sha512"
"crypto/x509"
"encoding/pem"
"fmt" "fmt"
"math/big" "math/big"
@@ -34,12 +36,14 @@ func GenerateKeyPair() (PublicKey, PrivateKey, error) {
} }
// PublicKeyFromBytes converts a serialized public key to a 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. // It errors if the slice is not the right size.
func PublicKeyFromBytes(b []byte) (PublicKey, error) { func PublicKeyFromBytes(b []byte) (PublicKey, error) {
return ecdh.X25519().NewPublicKey(b) return ecdh.X25519().NewPublicKey(b)
} }
// PublicKeyToBytes converts a public key to a byte slice. // PublicKeyToBytes converts a public key to a byte slice.
// This compact serialization format is the raw key material, without metadata or structure.
func PublicKeyToBytes(pub PublicKey) []byte { func PublicKeyToBytes(pub PublicKey) []byte {
return pub.Bytes() return pub.Bytes()
} }
@@ -121,13 +125,54 @@ func PublicKeyToMultibase(pub PublicKey) string {
return helpers.MultibaseEncode(MultibaseCode, pub.Bytes()) return helpers.MultibaseEncode(MultibaseCode, pub.Bytes())
} }
// PublicKeyFromX509DER decodes an X.509 DER (binary) encoded public key.
func PublicKeyFromX509DER(bytes []byte) (PublicKey, error) {
pub, err := x509.ParsePKIXPublicKey(bytes)
if err != nil {
return nil, err
}
return pub.(PublicKey), nil
}
// PublicKeyToX509DER encodes the public key into the X.509 DER (binary) format.
func PublicKeyToX509DER(pub PublicKey) []byte {
res, _ := x509.MarshalPKIXPublicKey(pub)
return res
}
const pemPubBlockType = "PUBLIC KEY"
// 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)
}
// PublicKeyToX509PEM encodes the public key into the X.509 PEM (binary) format.
func PublicKeyToX509PEM(pub PublicKey) string {
der := PublicKeyToX509DER(pub)
return string(pem.EncodeToMemory(&pem.Block{
Type: pemPubBlockType,
Bytes: der,
}))
}
// PrivateKeyFromBytes converts a serialized private key to a PrivateKey. // PrivateKeyFromBytes converts a serialized private key to a PrivateKey.
// This compact serialization format is the raw key material, without metadata or structure.
// It errors if len(privateKey) is not [PrivateKeySize]. // It errors if len(privateKey) is not [PrivateKeySize].
func PrivateKeyFromBytes(b []byte) (PrivateKey, error) { func PrivateKeyFromBytes(b []byte) (PrivateKey, error) {
// this already check the size of b
return ecdh.X25519().NewPrivateKey(b) return ecdh.X25519().NewPrivateKey(b)
} }
// PrivateKeyToBytes converts a private key to a byte slice. // PrivateKeyToBytes converts a private key to a byte slice.
// This compact serialization format is the raw key material, without metadata or structure.
func PrivateKeyToBytes(priv PrivateKey) []byte { func PrivateKeyToBytes(priv PrivateKey) []byte {
return priv.Bytes() return priv.Bytes()
} }
@@ -154,6 +199,44 @@ func PrivateKeyFromEd25519(priv ed25519.PrivateKey) (PrivateKey, error) {
return ecdh.X25519().NewPrivateKey(h[:32]) return ecdh.X25519().NewPrivateKey(h[:32])
} }
// PrivateKeyFromPKCS8DER decodes a PKCS#8 DER (binary) encoded private key.
func PrivateKeyFromPKCS8DER(bytes []byte) (PrivateKey, error) {
priv, err := x509.ParsePKCS8PrivateKey(bytes)
if err != nil {
return nil, err
}
return priv.(PrivateKey), nil
}
// PrivateKeyToPKCS8DER encodes the private key into the PKCS#8 DER (binary) format.
func PrivateKeyToPKCS8DER(priv PrivateKey) []byte {
res, _ := x509.MarshalPKCS8PrivateKey(priv)
return res
}
const pemPrivBlockType = "PRIVATE KEY"
// 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)
}
// PrivateKeyToPKCS8PEM encodes the private key into the PKCS#8 PEM (binary) format.
func PrivateKeyToPKCS8PEM(priv PrivateKey) string {
der := PrivateKeyToPKCS8DER(priv)
return string(pem.EncodeToMemory(&pem.Block{
Type: pemPrivBlockType,
Bytes: der,
}))
}
func reverseBytes(b []byte) []byte { func reverseBytes(b []byte) []byte {
r := make([]byte, len(b)) r := make([]byte, len(b))
for i := 0; i < len(b); i++ { for i := 0; i < len(b); i++ {

View File

@@ -2,6 +2,7 @@ package x25519_test
import ( import (
"crypto/ecdh" "crypto/ecdh"
"fmt"
"testing" "testing"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@@ -25,11 +26,13 @@ func TestBytesRoundTrip(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
bytes := x25519.PublicKeyToBytes(pub) bytes := x25519.PublicKeyToBytes(pub)
fmt.Println("pub", len(bytes))
rtPub, err := x25519.PublicKeyFromBytes(bytes) rtPub, err := x25519.PublicKeyFromBytes(bytes)
require.NoError(t, err) require.NoError(t, err)
require.True(t, pub.Equal(rtPub)) require.True(t, pub.Equal(rtPub))
bytes = x25519.PrivateKeyToBytes(priv) bytes = x25519.PrivateKeyToBytes(priv)
fmt.Println("priv", len(bytes))
rtPriv, err := x25519.PrivateKeyFromBytes(bytes) rtPriv, err := x25519.PrivateKeyFromBytes(bytes)
require.NoError(t, err) require.NoError(t, err)
require.True(t, priv.Equal(rtPriv)) require.True(t, priv.Equal(rtPriv))
@@ -45,6 +48,42 @@ func TestMultibaseRoundTrip(t *testing.T) {
require.Equal(t, pub, rt) require.Equal(t, pub, rt)
} }
func TestPublicKeyX509RoundTrip(t *testing.T) {
pub, _, err := ed25519.GenerateKeyPair()
require.NoError(t, err)
der := ed25519.PublicKeyToX509DER(pub)
fmt.Println("der", len(der))
rt, err := ed25519.PublicKeyFromX509DER(der)
require.NoError(t, err)
require.True(t, pub.Equal(rt))
pem := ed25519.PublicKeyToX509PEM(pub)
fmt.Println("pem", len(pem))
rt, err = ed25519.PublicKeyFromX509PEM(pem)
require.NoError(t, err)
require.True(t, pub.Equal(rt))
}
func TestPrivateKeyPKCS8RoundTrip(t *testing.T) {
pub, priv, err := ed25519.GenerateKeyPair()
require.NoError(t, err)
der := ed25519.PrivateKeyToPKCS8DER(priv)
fmt.Println("der", len(der))
rt, err := ed25519.PrivateKeyFromPKCS8DER(der)
require.NoError(t, err)
require.True(t, priv.Equal(rt))
require.True(t, pub.Equal(rt.Public()))
pem := ed25519.PrivateKeyToPKCS8PEM(priv)
fmt.Println("pem", len(pem))
rt, err = ed25519.PrivateKeyFromPKCS8PEM(pem)
require.NoError(t, err)
require.True(t, priv.Equal(rt))
require.True(t, pub.Equal(rt.Public()))
}
func TestEd25519ToX25519(t *testing.T) { func TestEd25519ToX25519(t *testing.T) {
// Known pubkey ed25519 --> x25519 // Known pubkey ed25519 --> x25519
for _, tc := range []struct { for _, tc := range []struct {