emmansun / gmsm

ShangMi (SM) cipher suites for golang (Go语言商用密码软件)

Home Page:https://emmansun.github.io/gmsm

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

OpenSSL generated SM2 key throws error on parsing

truekarthik opened this issue · comments

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

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.

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

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!

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

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?

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.

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

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

openssl 3.2.1 will fix it.

openssl 3.2.1 will fix it.

openssl/openssl#22529