2 years ago
#60097
Madis Apsalon
How to export ed25519 public key from []*pkcs11.Attribute
- I generated an ed25519 key pair with golang PKCS11 library branch v3 (it is connected to SoftHSM2):
publicKeyTemplate := []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PUBLIC_KEY),
pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, false),
pkcs11.NewAttribute(pkcs11.CKA_LABEL, "go_ed_3"),
pkcs11.NewAttribute(pkcs11.CKA_TRUSTED, false),
pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_EC_EDWARDS),
pkcs11.NewAttribute(pkcs11.CKA_ID, 1234),
pkcs11.NewAttribute(pkcs11.CKA_ENCRYPT, false),
pkcs11.NewAttribute(pkcs11.CKA_WRAP, false),
pkcs11.NewAttribute(pkcs11.CKA_VERIFY, false),
pkcs11.NewAttribute(pkcs11.CKA_VERIFY_RECOVER, false),
pkcs11.NewAttribute(pkcs11.CKA_DERIVE, false),
pkcs11.NewAttribute(pkcs11.CKA_MODIFIABLE, true),
pkcs11.NewAttribute(pkcs11.CKA_COPYABLE, true),
pkcs11.NewAttribute(pkcs11.CKA_DESTROYABLE, true),
pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, []byte{0x13, 0x0c, 0x65, 0x64, 0x77, 0x61, 0x72, 0x64, 0x73, 0x32, 0x35, 0x35, 0x31, 0x39}),
}
// Set private key template
privateKeyTemplate := []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY),
pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, true),
pkcs11.NewAttribute(pkcs11.CKA_LABEL, "go_ed_3"),
pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_EC_EDWARDS),
pkcs11.NewAttribute(pkcs11.CKA_ID, 1234),
}
mechanism := []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_EC_EDWARDS_KEY_PAIR_GEN, nil)}
pub, pri, err := p.GenerateKeyPair(session, mechanism, publicKeyTemplate, privateKeyTemplate)
if err != nil {
fmt.Println("Key generation failed:", err)
return
}
spew.Dump(pub)
spew.Dump(pri)
- Using pkcs11-tools I checked that the key pair is generated successfully and the public key is following:
p11cat pubk/go_ed_2
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEA9JJpbH0+hBryC0zcSdeFwa57up4l4/umPTcZzowSI4Q=
-----END PUBLIC KEY-----
- So now I would like to export the public key with my code. I found the public key object:
ktemplate := []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PUBLIC_KEY),
pkcs11.NewAttribute(pkcs11.CKA_ID, 1234),
pkcs11.NewAttribute(pkcs11.CKA_LABEL, "go_ed_2"),
}
if err := p.FindObjectsInit(session, ktemplate); err != nil {
panic(err)
}
objs, _, err := p.FindObjects(session, 1)
if err != nil {
panic(err)
}
if err = p.FindObjectsFinal(session); err != nil {
panic(err)
}
fmt.Println("Objects found:", objs[0])
attr, err := p.GetAttributeValue(session, objs[0], []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, nil),
pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, nil),
})
if err != nil {
panic(err)
}
fmt.Println("attr:", attr[0].Value)
The main question is how can I export the proper ed25519 public key from that?
I did plenty of research but I have not found an answer for that. I know that RSA public key exporting works following:
pr, err := p.GetAttributeValue(session, pbk, []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_MODULUS, nil),
pkcs11.NewAttribute(pkcs11.CKA_PUBLIC_EXPONENT, nil),
})
if err != nil {
panic(err)
}
modulus := new(big.Int)
modulus.SetBytes(pr[0].Value)
bigExponent := new(big.Int)
bigExponent.SetBytes(pr[1].Value)
exponent := int(bigExponent.Uint64())
rsaPub := &rsa.PublicKey{
N: modulus,
E: exponent,
}
pubkeyPem := string(pem.EncodeToMemory(&pem.Block{Type: "RSA PUBLIC KEY", Bytes: x509.MarshalPKCS1PublicKey(rsaPub)}))
log.Printf(" Public Key: \n%s\n", pubkeyPem)
And for elliptic keys something similar should be used exportECDSAPublicKey, but it is not the case with ed25519
func exportECDSAPublicKey(session *pkcs11Session, pubHandle pkcs11.ObjectHandle) (crypto.PublicKey, error) {
var err error
var attributes []*pkcs11.Attribute
var pub ecdsa.PublicKey
template := []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_ECDSA_PARAMS, nil),
pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, nil),
}
if attributes, err = session.ctx.GetAttributeValue(session.handle, pubHandle, template); err != nil {
return nil, err
}
if pub.Curve, err = unmarshalEcParams(attributes[0].Value); err != nil {
return nil, err
}
if pub.X, pub.Y, err = unmarshalEcPoint(attributes[1].Value, pub.Curve); err != nil {
return nil, err
}
return &pub, nil
}
go
pkcs#11
ed25519
0 Answers
Your Answer