Go语言 如何从[]*pkcs11.Attribute导出ed25519公钥

bmvo0sr5  于 2023-11-14  发布在  Go
关注(0)|答案(1)|浏览(144)

1.我用golang PKCS11 library branch v3生成了一个ed25519密钥对(它连接到SoftHSM 2):

  1. publicKeyTemplate := []*pkcs11.Attribute{
  2. pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PUBLIC_KEY),
  3. pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
  4. pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, false),
  5. pkcs11.NewAttribute(pkcs11.CKA_LABEL, "go_ed_3"),
  6. pkcs11.NewAttribute(pkcs11.CKA_TRUSTED, false),
  7. pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_EC_EDWARDS),
  8. pkcs11.NewAttribute(pkcs11.CKA_ID, 1234),
  9. pkcs11.NewAttribute(pkcs11.CKA_ENCRYPT, false),
  10. pkcs11.NewAttribute(pkcs11.CKA_WRAP, false),
  11. pkcs11.NewAttribute(pkcs11.CKA_VERIFY, false),
  12. pkcs11.NewAttribute(pkcs11.CKA_VERIFY_RECOVER, false),
  13. pkcs11.NewAttribute(pkcs11.CKA_DERIVE, false),
  14. pkcs11.NewAttribute(pkcs11.CKA_MODIFIABLE, true),
  15. pkcs11.NewAttribute(pkcs11.CKA_COPYABLE, true),
  16. pkcs11.NewAttribute(pkcs11.CKA_DESTROYABLE, true),
  17. pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, []byte{0x13, 0x0c, 0x65, 0x64, 0x77, 0x61, 0x72, 0x64, 0x73, 0x32, 0x35, 0x35, 0x31, 0x39}),
  18. }
  19. // Set private key template
  20. privateKeyTemplate := []*pkcs11.Attribute{
  21. pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY),
  22. pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
  23. pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, true),
  24. pkcs11.NewAttribute(pkcs11.CKA_LABEL, "go_ed_3"),
  25. pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_EC_EDWARDS),
  26. pkcs11.NewAttribute(pkcs11.CKA_ID, 1234),
  27. }
  28. mechanism := []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_EC_EDWARDS_KEY_PAIR_GEN, nil)}
  29. pub, pri, err := p.GenerateKeyPair(session, mechanism, publicKeyTemplate, privateKeyTemplate)
  30. if err != nil {
  31. fmt.Println("Key generation failed:", err)
  32. return
  33. }
  34. spew.Dump(pub)
  35. spew.Dump(pri)

字符串
1.使用pkcs11-tools,我检查了密钥对是否成功生成,公钥如下:

  1. p11cat pubk/go_ed_2
  2. -----BEGIN PUBLIC KEY-----
  3. MCowBQYDK2VwAyEA9JJpbH0+hBryC0zcSdeFwa57up4l4/umPTcZzowSI4Q=
  4. -----END PUBLIC KEY-----


1.所以现在我想用我的代码导出公钥。我找到了公钥对象:

  1. ktemplate := []*pkcs11.Attribute{
  2. pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PUBLIC_KEY),
  3. pkcs11.NewAttribute(pkcs11.CKA_ID, 1234),
  4. pkcs11.NewAttribute(pkcs11.CKA_LABEL, "go_ed_2"),
  5. }
  6. if err := p.FindObjectsInit(session, ktemplate); err != nil {
  7. panic(err)
  8. }
  9. objs, _, err := p.FindObjects(session, 1)
  10. if err != nil {
  11. panic(err)
  12. }
  13. if err = p.FindObjectsFinal(session); err != nil {
  14. panic(err)
  15. }
  16. fmt.Println("Objects found:", objs[0])
  17. attr, err := p.GetAttributeValue(session, objs[0], []*pkcs11.Attribute{
  18. pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, nil),
  19. pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, nil),
  20. })
  21. if err != nil {
  22. panic(err)
  23. }
  24. fmt.Println("attr:", attr[0].Value)


主要的问题是我如何才能从中导出正确的ed25519公钥?
我做了大量的研究,但我还没有找到答案。我知道RSA公钥导出工作如下:

  1. pr, err := p.GetAttributeValue(session, pbk, []*pkcs11.Attribute{
  2. pkcs11.NewAttribute(pkcs11.CKA_MODULUS, nil),
  3. pkcs11.NewAttribute(pkcs11.CKA_PUBLIC_EXPONENT, nil),
  4. })
  5. if err != nil {
  6. panic(err)
  7. }
  8. modulus := new(big.Int)
  9. modulus.SetBytes(pr[0].Value)
  10. bigExponent := new(big.Int)
  11. bigExponent.SetBytes(pr[1].Value)
  12. exponent := int(bigExponent.Uint64())
  13. rsaPub := &rsa.PublicKey{
  14. N: modulus,
  15. E: exponent,
  16. }
  17. pubkeyPem := string(pem.EncodeToMemory(&pem.Block{Type: "RSA PUBLIC KEY", Bytes: x509.MarshalPKCS1PublicKey(rsaPub)}))
  18. log.Printf(" Public Key: \n%s\n", pubkeyPem)


对于椭圆密钥,应该使用类似的exportECDSAPublicKey,但ed25519不是这种情况

  1. func exportECDSAPublicKey(session *pkcs11Session, pubHandle pkcs11.ObjectHandle) (crypto.PublicKey, error) {
  2. var err error
  3. var attributes []*pkcs11.Attribute
  4. var pub ecdsa.PublicKey
  5. template := []*pkcs11.Attribute{
  6. pkcs11.NewAttribute(pkcs11.CKA_ECDSA_PARAMS, nil),
  7. pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, nil),
  8. }
  9. if attributes, err = session.ctx.GetAttributeValue(session.handle, pubHandle, template); err != nil {
  10. return nil, err
  11. }
  12. if pub.Curve, err = unmarshalEcParams(attributes[0].Value); err != nil {
  13. return nil, err
  14. }
  15. if pub.X, pub.Y, err = unmarshalEcPoint(attributes[1].Value, pub.Curve); err != nil {
  16. return nil, err
  17. }
  18. return &pub, nil
  19. }

ou6hu8tu

ou6hu8tu1#

既然已经过了这么久,也许只是为了完成这个问题。
它实际上是

  1. template := []*pkcs11.Attribute{
  2. pkcs11.NewAttribute(pkcs11.CKA_ECDSA_PARAMS, nil),
  3. pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, nil),
  4. }

字符串
只不过你得去掉前两个字节

  1. import "crypto/ed25519"
  2. pkbytes := attr[1].Value[2:]
  3. pubKey := ed25519.PublicKey(pkbytes)
  4. fmt.Println("pub key:", hex.EncodeToString(pubKey))


如果你可以导出私钥(种子),你可以验证。

  1. attr, err = p.GetAttributeValue(session, privateObjectHandle, []*pkcs11.Attribute{
  2. pkcs11.NewAttribute(pkcs11.CKA_VALUE, nil),
  3. })
  4. if err != nil {
  5. panic(err)
  6. }
  7. seedBytes := attr[0].Value
  8. privKey := ed25519.NewKeyFromSeed(seedBytes)
  9. publicKey := privKey[32:]
  10. fmt.Println("pub key:", hex.EncodeToString(ppk))

展开查看全部

相关问题