Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenSSL generated SM2 key throws error on parsing #197

Closed
coder-whale opened this issue Jan 8, 2024 · 10 comments
Closed

OpenSSL generated SM2 key throws error on parsing #197

coder-whale opened this issue Jan 8, 2024 · 10 comments

Comments

@coder-whale
Copy link

Trying to parse an SM2 private key created using OpenSSL throws an error - x509: PKCS#8 wrapping contained private key with unknown algorithm: 1.2.156.10197.1.301

Versions:
OpenSSL - v3.1.3
emmansun/gmsm - v0.24.1

Steps to reproduce the error:

  1. Generate SM2 Private key using OpenSSL:
    openssl ecparam -name SM2 -genkey -noout -out private-key.pem

  2. Use the returned key string in the below code:

package main

import (
	"encoding/pem"
	"fmt"

	"github.com/emmansun/gmsm/pkcs8"
)

func main() {
	privateKey := "-----BEGIN PRIVATE KEY-----\nMIGIAgEAMBQGCCqBHM9VAYItBggqgRzPVQGCLQRtMGsCAQEEIIfYbABfRJN5ZBkW\nteXxzV0hzNrWBhN0Fmn0cJRqy50XoUQDQgAEbyM/EfFVSXAdxeZ3ovXSAtG3GD1v\nav+xanZVivqzzKU35ILFbXef9YkxHQOpQRRifIj99nJS7SH+cFH5S0jKLw==\n-----END PRIVATE KEY-----\n"
	keyData := []byte(privateKey)
	block, _ := pem.Decode(keyData)
	_, err := pkcs8.ParsePKCS8PrivateKeySM2(block.Bytes)
	fmt.Println(err)
}

Error returned is x509: PKCS#8 wrapping contained private key with unknown algorithm: 1.2.156.10197.1.301

@coder-whale
Copy link
Author

Digging deeper into the code using a debugger, the ObjectIdentifier of this key's algorithm is oidNamedCurveP256SM2 but in this block of the code in line 52 of smx509/pkcs8.go,

gmsm/smx509/pkcs8.go

Lines 52 to 54 in ceff9bf

if !privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA) {
return x509.ParsePKCS8PrivateKey(der)
}

there is a not operator provided in the if condition, resulting in return x509.ParsePKCS8PrivateKey(der) being executed which throws the error.

Am I missing something here or is this a bug? Thanks in advance.

@emmansun
Copy link
Owner

emmansun commented Jan 8, 2024

Are you sure this is the pkcs8 private key? Looks more like SEC1 ECC private key.

@emmansun
Copy link
Owner

emmansun commented Jan 9, 2024

Per double checking, it seems the sm2 pkcs8 private key format in OpenSSL v3.1.3 is different with my understanding:

image

Let me double check the change and if there are standards for it.

Thx!

@emmansun
Copy link
Owner

emmansun commented Jan 9, 2024

It seems that many people disapprove of this implementation of openssl. openssl/openssl#22529, let me make this library compatible with this implementation first.

@coder-whale
Copy link
Author

Thanks for the quick fix. Does this mean that this library is not compatible with OpenSSL SM2 keys and other functions like Sign/Verify may also not work with OpenSSL generated SM2 keys?

@emmansun
Copy link
Owner

emmansun commented Jan 9, 2024

Thanks for the quick fix. Does this mean that this library is not compatible with OpenSSL SM2 keys and other functions like Sign/Verify may also not work with OpenSSL generated SM2 keys?

There are standards for SM2 Sign/Verify, Encrypt/Decrypt and so on, for the SM2 private key pkcs8 , there are no related national standards yet, we just treat SM2 private key similar like other NIST elliptic curves: NIST P224 NIST P256 NIST P382 NIST P521.

// pkcs8 reflects an ASN.1, PKCS #8 PrivateKey. See
// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn
// and RFC 5208.
type pkcs8 struct {
	Version    int
	Algo       pkix.AlgorithmIdentifier
	PrivateKey []byte
	// optional attributes omitted.
}

// AlgorithmIdentifier represents the ASN.1 structure of the same name. See RFC
// 5280, section 4.1.1.2.
type AlgorithmIdentifier struct {
	Algorithm  asn1.ObjectIdentifier
	Parameters asn1.RawValue `asn1:"optional"`
}

That means Algo.Algorithm is

	// RFC 5480, 2.1.1 Unrestricted Algorithm Identifier and Parameters
	//
	//	id-ecPublicKey OBJECT IDENTIFIER ::= {
	//		iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 }
	oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}

and Alg.Parameters will be the real Curve OID. I think there are more discussions in

So, we also can't say it's a fix, but just an enhancement to support such kind of openssl 3+ sm2 p8 format private key.

In general , if openssl 3+ used 1.2.156.10197.1.301 to replace 1.2.2840.10045.2.1 in pkcs8 private key, PKIX public key, csr, certificate, then there will be interoperability issues with most of implementations, Sign/Verify functions may not be impacted, but the prerequisite is that you can parse them.

Per checking those openssl 3 disucssions, issues, pulls, it seems smx509: can parse openssl v3.1.3 p8 sm2 private key is NOT enough, if you need to parse sm2 PKIX public, csr, certificate generated by openssl 3+, you will still encounter issues.

@emmansun
Copy link
Owner

emmansun commented Jan 9, 2024

Let’s see if openssl3 will stick to its own opinion or change it to backward compatibility.

@coder-whale
Copy link
Author

Thanks a lot for the detailed explanation. You can close the issue if you'd like.

@emmansun
Copy link
Owner

openssl 3.2.1 will fix it.

@emmansun
Copy link
Owner

openssl 3.2.1 will fix it.

openssl/openssl#22529

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants