55 "crypto/elliptic"
66 "crypto/rand"
77 "crypto/x509"
8+ "encoding/pem"
89 "fmt"
10+ "math/big"
911
1012 helpers "github.com/INFURA/go-did/verifications/internal"
1113)
@@ -15,8 +17,8 @@ type PrivateKey = *ecdsa.PrivateKey
1517
1618const (
1719 // TODO
18- PublicKeySize = 123456
19- PrivateKeySize = 123456
20+ PublicKeySize = 33
21+ PrivateKeySize = 32
2022 SignatureSize = 123456
2123
2224 MultibaseCode = uint64 (0x1200 )
@@ -31,6 +33,7 @@ func GenerateKeyPair() (PublicKey, PrivateKey, error) {
3133}
3234
3335// PublicKeyFromBytes converts a serialized public key to a PublicKey.
36+ // This compact serialization format is the raw key material, without metadata or structure.
3437// It errors if the slice is not the right size.
3538func PublicKeyFromBytes (b []byte ) (PublicKey , error ) {
3639 if len (b ) != PublicKeySize {
@@ -41,17 +44,25 @@ func PublicKeyFromBytes(b []byte) (PublicKey, error) {
4144 return nil , fmt .Errorf ("invalid P-256 public key" )
4245 }
4346 return & ecdsa.PublicKey {Curve : elliptic .P256 (), X : x , Y : y }, nil
47+
48+ // if len(b) != PublicKeySize {
49+ // return nil, fmt.Errorf("invalid P-256 public key size")
50+ // }
51+ // x := new(big.Int).SetBytes(b[:PublicKeySize/2])
52+ // y := new(big.Int).SetBytes(b[PublicKeySize/2:])
53+ // return &ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}, nil
4454}
4555
4656// PublicKeyToBytes converts a public key to a byte slice.
47- func PublicKeyToBytes (pub PublicKey ) (res []byte , err error ) {
48- defer func () {
49- if rerr := recover (); rerr != nil {
50- err = fmt .Errorf ("recovered panic: %s" , rerr )
51- res = nil
52- }
53- }()
54- return x509 .MarshalPKIXPublicKey (pub )
57+ // This compact serialization format is the raw key material, without metadata or structure.
58+ func PublicKeyToBytes (pub PublicKey ) []byte {
59+ return elliptic .MarshalCompressed (elliptic .P256 (), pub .X , pub .Y )
60+
61+ // // fixed size buffer that can get allocated on the caller's stack after inlining.
62+ // var buf [PublicKeySize]byte
63+ // pub.X.FillBytes(buf[:PublicKeySize/2])
64+ // pub.Y.FillBytes(buf[PublicKeySize/2:])
65+ // return buf[:]
5566}
5667
5768// PublicKeyFromMultibase decodes the public key from its Multibase form
@@ -72,13 +83,106 @@ func PublicKeyToMultibase(pub PublicKey) string {
7283 return helpers .MultibaseEncode (MultibaseCode , bytes )
7384}
7485
86+ // PublicKeyFromX509DER decodes an X.509 DER (binary) encoded public key.
87+ func PublicKeyFromX509DER (bytes []byte ) (PublicKey , error ) {
88+ pub , err := x509 .ParsePKIXPublicKey (bytes )
89+ if err != nil {
90+ return nil , err
91+ }
92+ return pub .(PublicKey ), nil
93+ }
94+
95+ // PublicKeyToX509DER encodes the public key into the X.509 DER (binary) format.
96+ func PublicKeyToX509DER (pub PublicKey ) []byte {
97+ res , _ := x509 .MarshalPKIXPublicKey (pub )
98+ return res
99+ }
100+
101+ const pemPubBlockType = "PUBLIC KEY"
102+
103+ // PublicKeyFromX509PEM decodes an X.509 PEM (string) encoded public key.
104+ func PublicKeyFromX509PEM (str string ) (PublicKey , error ) {
105+ block , _ := pem .Decode ([]byte (str ))
106+ if block == nil {
107+ return nil , fmt .Errorf ("failed to decode PEM block" )
108+ }
109+ if block .Type != pemPubBlockType {
110+ return nil , fmt .Errorf ("incorrect PEM block type" )
111+ }
112+ return PublicKeyFromX509DER (block .Bytes )
113+ }
114+
115+ // PublicKeyToX509PEM encodes the public key into the X.509 PEM (binary) format.
116+ func PublicKeyToX509PEM (pub PublicKey ) string {
117+ der := PublicKeyToX509DER (pub )
118+ return string (pem .EncodeToMemory (& pem.Block {
119+ Type : pemPubBlockType ,
120+ Bytes : der ,
121+ }))
122+ }
123+
75124// PrivateKeyFromBytes converts a serialized public key to a PrivateKey.
125+ // This compact serialization format is the raw key material, without metadata or structure.
76126// It errors if the slice is not the right size.
77127func PrivateKeyFromBytes (b []byte ) (PrivateKey , error ) {
78128 if len (b ) != PrivateKeySize {
79129 return nil , fmt .Errorf ("invalid P-256 private key size" )
80130 }
81- // TODO
82131
83- return nil , nil
132+ res := & ecdsa.PrivateKey {
133+ D : new (big.Int ).SetBytes (b ),
134+ PublicKey : ecdsa.PublicKey {Curve : elliptic .P256 ()},
135+ }
136+
137+ // recompute the public key
138+ res .PublicKey .X , res .PublicKey .Y = res .PublicKey .Curve .ScalarBaseMult (b )
139+
140+ return res , nil
141+ }
142+
143+ // PrivateKeyToBytes converts a private key to a byte slice.
144+ // This compact serialization format is the raw key material, without metadata or structure.
145+ func PrivateKeyToBytes (priv PrivateKey ) []byte {
146+ // fixed size buffer that can get allocated on the caller's stack after inlining.
147+ var buf [PrivateKeySize ]byte
148+ priv .D .FillBytes (buf [:])
149+ return buf [:]
150+ }
151+
152+ // PrivateKeyFromPKCS8DER decodes a PKCS#8 DER (binary) encoded private key.
153+ func PrivateKeyFromPKCS8DER (bytes []byte ) (PrivateKey , error ) {
154+ priv , err := x509 .ParsePKCS8PrivateKey (bytes )
155+ if err != nil {
156+ return nil , err
157+ }
158+ return priv .(PrivateKey ), nil
159+ }
160+
161+ // PrivateKeyToPKCS8DER encodes the private key into the PKCS#8 DER (binary) format.
162+ func PrivateKeyToPKCS8DER (priv PrivateKey ) []byte {
163+ res , _ := x509 .MarshalPKCS8PrivateKey (priv )
164+ return res
165+ }
166+
167+ const pemPrivBlockType = "PRIVATE KEY"
168+
169+ // PrivateKeyFromPKCS8PEM decodes an PKCS#8 PEM (string) encoded private key.
170+ func PrivateKeyFromPKCS8PEM (str string ) (PrivateKey , error ) {
171+ block , _ := pem .Decode ([]byte (str ))
172+ if block == nil {
173+ return nil , fmt .Errorf ("failed to decode PEM block" )
174+ }
175+ if block .Type != pemPrivBlockType {
176+ return nil , fmt .Errorf ("incorrect PEM block type" )
177+ }
178+ return PrivateKeyFromPKCS8DER (block .Bytes )
179+ }
180+
181+ // PrivateKeyToPKCS8PEM encodes the private key into the PKCS#8 PEM (binary) format.
182+ func PrivateKeyToPKCS8PEM (priv PrivateKey ) string {
183+ der := PrivateKeyToPKCS8DER (priv )
184+ return string (pem .EncodeToMemory (& pem.Block {
185+ Type : pemPrivBlockType ,
186+ Bytes : der ,
187+ }))
84188}
0 commit comments