From 9e57bb91b2b05d32bc7a2eef84133d8b866d7d10 Mon Sep 17 00:00:00 2001 From: Sun Yimin Date: Thu, 23 Jan 2025 11:28:54 +0800 Subject: [PATCH] cfca: add examples --- cfca/example_test.go | 180 ++++++++++++++++++++++++++++++++++++++++ cfca/pkcs12_sm2.go | 2 +- cfca/pkcs12_sm2_test.go | 4 +- docs/cfca.md | 2 +- 4 files changed, 184 insertions(+), 4 deletions(-) create mode 100644 cfca/example_test.go diff --git a/cfca/example_test.go b/cfca/example_test.go new file mode 100644 index 0000000..03f8c8f --- /dev/null +++ b/cfca/example_test.go @@ -0,0 +1,180 @@ +package cfca_test + +import ( + "crypto/ecdsa" + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" + "encoding/base64" + "encoding/hex" + "encoding/pem" + "fmt" + + "github.com/emmansun/gmsm/cfca" + "github.com/emmansun/gmsm/sm2" +) + +func ExampleParseSM2() { + base64data := ` +MIIDSQIBATBHBgoqgRzPVQYBBAIBBgcqgRzPVQFoBDDkLvKllj9ZWhaKU6MSnxBBV5yaF3tEcOk1 +vQniWyVzyaQA4F3j/YvDJwEoE8gOF/swggL5BgoqgRzPVQYBBAIBBIIC6TCCAuUwggKJoAMCAQIC +BRBAmQgJMAwGCCqBHM9VAYN1BQAwXDELMAkGA1UEBhMCQ04xMDAuBgNVBAoMJ0NoaW5hIEZpbmFu +Y2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEbMBkGA1UEAwwSQ0ZDQSBURVNUIFNNMiBPQ0Ex +MB4XDTIwMTExOTA4MzExOFoXDTI1MTExOTA4MzExOFowgYkxCzAJBgNVBAYTAkNOMRcwFQYDVQQK +DA5DRkNBIFRFU1QgT0NBMTENMAsGA1UECwwEUFNCQzEZMBcGA1UECwwQT3JnYW5pemF0aW9uYWwt +MjE3MDUGA1UEAwwuMDUxQOmCruWCqOe6v+S4iuaUtuWNleWVhuaIt0BONTEwMTEzMDAwMTg4NzhA +MTBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABJVRC63OKfcL4H324rDOdb4SSlbAjoJDXnK0qmwX +Z59FWmiSqt3ipreljKew4QynjTgR/yfp9yjNgNU8G5pkYdujggEGMIIBAjAfBgNVHSMEGDAWgBRr +/hjaj0I6prhtsy6Igzo0osEw4TAMBgNVHRMBAf8EAjAAMEgGA1UdIARBMD8wPQYIYIEchu8qAQEw +MTAvBggrBgEFBQcCARYjaHR0cDovL3d3dy5jZmNhLmNvbS5jbi91cy91cy0xNC5odG0wOQYDVR0f +BDIwMDAuoCygKoYoaHR0cDovL3VjcmwuY2ZjYS5jb20uY24vU00yL2NybDE0MzU2LmNybDAOBgNV +HQ8BAf8EBAMCBsAwHQYDVR0OBBYEFPiGPZT0oTuRXvkyGoOgviNEWnc1MB0GA1UdJQQWMBQGCCsG +AQUFBwMCBggrBgEFBQcDBDAMBggqgRzPVQGDdQUAA0gAMEUCIQCJDSsVPfhr+gnDASMj5Syt+hxs +amHygPecjCLbcdFQQgIgSXC4musF5Fnj/CpNTqvk9+56FuINkATGS8xRh7kzKBE=` + password := []byte("123456") + data, err := base64.StdEncoding.DecodeString(base64data) + if err != nil { + panic(err) + } + priv, cert, err := cfca.ParseSM2(password, data) + if err != nil { + panic(err) + } + fmt.Printf("%x\n", priv.D.Bytes()) + fmt.Printf("%v\n", cert.Issuer) + // Output: d3f24d61bb2816882b8474b778dd7c3166d665f9455dc9d551c989c161e76ab0 + // CN=CFCA TEST SM2 OCA1,O=China Financial Certification Authority,C=CN +} + +func ExampleParseSM2_pemEncoded() { + pemdata := ` +-----BEGIN CFCA KEY----- +MIIDSQIBATBHBgoqgRzPVQYBBAIBBgcqgRzPVQFoBDDkLvKllj9ZWhaKU6MSnxBBV5yaF3tEcOk1 +vQniWyVzyaQA4F3j/YvDJwEoE8gOF/swggL5BgoqgRzPVQYBBAIBBIIC6TCCAuUwggKJoAMCAQIC +BRBAmQgJMAwGCCqBHM9VAYN1BQAwXDELMAkGA1UEBhMCQ04xMDAuBgNVBAoMJ0NoaW5hIEZpbmFu +Y2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEbMBkGA1UEAwwSQ0ZDQSBURVNUIFNNMiBPQ0Ex +MB4XDTIwMTExOTA4MzExOFoXDTI1MTExOTA4MzExOFowgYkxCzAJBgNVBAYTAkNOMRcwFQYDVQQK +DA5DRkNBIFRFU1QgT0NBMTENMAsGA1UECwwEUFNCQzEZMBcGA1UECwwQT3JnYW5pemF0aW9uYWwt +MjE3MDUGA1UEAwwuMDUxQOmCruWCqOe6v+S4iuaUtuWNleWVhuaIt0BONTEwMTEzMDAwMTg4NzhA +MTBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABJVRC63OKfcL4H324rDOdb4SSlbAjoJDXnK0qmwX +Z59FWmiSqt3ipreljKew4QynjTgR/yfp9yjNgNU8G5pkYdujggEGMIIBAjAfBgNVHSMEGDAWgBRr +/hjaj0I6prhtsy6Igzo0osEw4TAMBgNVHRMBAf8EAjAAMEgGA1UdIARBMD8wPQYIYIEchu8qAQEw +MTAvBggrBgEFBQcCARYjaHR0cDovL3d3dy5jZmNhLmNvbS5jbi91cy91cy0xNC5odG0wOQYDVR0f +BDIwMDAuoCygKoYoaHR0cDovL3VjcmwuY2ZjYS5jb20uY24vU00yL2NybDE0MzU2LmNybDAOBgNV +HQ8BAf8EBAMCBsAwHQYDVR0OBBYEFPiGPZT0oTuRXvkyGoOgviNEWnc1MB0GA1UdJQQWMBQGCCsG +AQUFBwMCBggrBgEFBQcDBDAMBggqgRzPVQGDdQUAA0gAMEUCIQCJDSsVPfhr+gnDASMj5Syt+hxs +amHygPecjCLbcdFQQgIgSXC4musF5Fnj/CpNTqvk9+56FuINkATGS8xRh7kzKBE= +-----END CFCA KEY-----` + password := []byte("123456") + block, _ := pem.Decode([]byte(pemdata)) + if block == nil { + panic("failed to decode PEM block") + } + priv, cert, err := cfca.ParseSM2(password, block.Bytes) + if err != nil { + panic(err) + } + fmt.Printf("%x\n", priv.D.Bytes()) + fmt.Printf("%v\n", cert.Issuer) + // Output: d3f24d61bb2816882b8474b778dd7c3166d665f9455dc9d551c989c161e76ab0 + // CN=CFCA TEST SM2 OCA1,O=China Financial Certification Authority,C=CN +} + +func ExampleMarshalSM2_changePassword() { + pemdata := ` +-----BEGIN CFCA KEY----- +MIIDSQIBATBHBgoqgRzPVQYBBAIBBgcqgRzPVQFoBDDkLvKllj9ZWhaKU6MSnxBBV5yaF3tEcOk1 +vQniWyVzyaQA4F3j/YvDJwEoE8gOF/swggL5BgoqgRzPVQYBBAIBBIIC6TCCAuUwggKJoAMCAQIC +BRBAmQgJMAwGCCqBHM9VAYN1BQAwXDELMAkGA1UEBhMCQ04xMDAuBgNVBAoMJ0NoaW5hIEZpbmFu +Y2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEbMBkGA1UEAwwSQ0ZDQSBURVNUIFNNMiBPQ0Ex +MB4XDTIwMTExOTA4MzExOFoXDTI1MTExOTA4MzExOFowgYkxCzAJBgNVBAYTAkNOMRcwFQYDVQQK +DA5DRkNBIFRFU1QgT0NBMTENMAsGA1UECwwEUFNCQzEZMBcGA1UECwwQT3JnYW5pemF0aW9uYWwt +MjE3MDUGA1UEAwwuMDUxQOmCruWCqOe6v+S4iuaUtuWNleWVhuaIt0BONTEwMTEzMDAwMTg4NzhA +MTBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABJVRC63OKfcL4H324rDOdb4SSlbAjoJDXnK0qmwX +Z59FWmiSqt3ipreljKew4QynjTgR/yfp9yjNgNU8G5pkYdujggEGMIIBAjAfBgNVHSMEGDAWgBRr +/hjaj0I6prhtsy6Igzo0osEw4TAMBgNVHRMBAf8EAjAAMEgGA1UdIARBMD8wPQYIYIEchu8qAQEw +MTAvBggrBgEFBQcCARYjaHR0cDovL3d3dy5jZmNhLmNvbS5jbi91cy91cy0xNC5odG0wOQYDVR0f +BDIwMDAuoCygKoYoaHR0cDovL3VjcmwuY2ZjYS5jb20uY24vU00yL2NybDE0MzU2LmNybDAOBgNV +HQ8BAf8EBAMCBsAwHQYDVR0OBBYEFPiGPZT0oTuRXvkyGoOgviNEWnc1MB0GA1UdJQQWMBQGCCsG +AQUFBwMCBggrBgEFBQcDBDAMBggqgRzPVQGDdQUAA0gAMEUCIQCJDSsVPfhr+gnDASMj5Syt+hxs +amHygPecjCLbcdFQQgIgSXC4musF5Fnj/CpNTqvk9+56FuINkATGS8xRh7kzKBE= +-----END CFCA KEY-----` + password := []byte("123456") + block, _ := pem.Decode([]byte(pemdata)) + if block == nil { + panic("failed to decode PEM block") + } + priv, cert, err := cfca.ParseSM2(password, block.Bytes) + if err != nil { + panic(err) + } + newpassword := []byte("654321") + data, err := cfca.MarshalSM2(newpassword, priv, cert) + if err != nil { + panic(err) + } + priv2, cert2, err := cfca.ParseSM2(newpassword, data) + if err != nil { + panic(err) + } + fmt.Printf("%x\n", priv2.D.Bytes()) + fmt.Printf("%v\n", cert2.Issuer) + // Output: d3f24d61bb2816882b8474b778dd7c3166d665f9455dc9d551c989c161e76ab0 + // CN=CFCA TEST SM2 OCA1,O=China Financial Certification Authority,C=CN +} + +func ExampleCreateCertificateRequest() { + keyBytes, _ := hex.DecodeString("6c5a0a0b2eed3cbec3e4f1252bfe0e28c504a1c6bf1999eebb0af9ef0f8e6c85") + priv, err := sm2.NewPrivateKey(keyBytes) + if err != nil { + panic(err) + } + random := rand.Reader + + // tmpKey used to decrypt the returned escrow PrivateKey + keyBytes, _ = hex.DecodeString("cacece36cac24aab94e52bcd5c0f552c95028f2856053135a1e47510b4c307ba") + tmpKey, err := sm2.NewPrivateKey(keyBytes) + if err != nil { + panic(err) + } + template := &x509.CertificateRequest{ + Subject: pkix.Name{ + CommonName: "certRequisition", + Organization: []string{"CFCA TEST CA"}, + Country: []string{"CN"}, + }, + } + csrder, err := cfca.CreateCertificateRequest(random, template, priv, &tmpKey.PublicKey, "123456") + if err != nil { + panic(err) + } + // you can encode the csrder to PEM format or base64 format + + csr, err := cfca.ParseCertificateRequest(csrder) + if err != nil { + panic(err) + } + fmt.Printf("%v\n", csr.Subject) + fmt.Printf("%v\n", csr.ChallengePassword) + fmt.Printf("%x\n", csr.TmpPublicKey.(*ecdsa.PublicKey).X) + // Output: CN=certRequisition,O=CFCA TEST CA,C=CN + // 123456 + // c7c4d0945ebdfc2111ad64b0e92e04582b0725fea172968c6c40162c810f8882 +} + +func ExampleParseEscrowPrivateKey() { + // a sample method to parse the escrow private key + keydata := `00000000000000010000000000000001000000000000000000000000000000000000000000000268MIHGAgEBBIHArhtKwTVT8dPEkykVRpvQNMxHv/yeqtaKZiSp2MbjcqMZtPfKW8IatiIPPitNhQtU5C7gMbsUxgf5Yo16vDSXdoWqoOOaes2pEJwmXWZI55lMMWc168WgzQ82fmMi05Vhlw9HNjGI3azE6MS5/ujSNGLZ0qAAmLnBiHlXFAXXAWRiy9MxZKwF4xKn6qMaKmkqbYmTbBbEJEhzJBmu0IJ1kNDcTFirAyapghHSw267erSUwsHjkQis9mKYpzGied0E` + keyBytes, _ := hex.DecodeString("cacece36cac24aab94e52bcd5c0f552c95028f2856053135a1e47510b4c307ba") + tmpKey, err := sm2.NewPrivateKey(keyBytes) + if err != nil { + panic(err) + } + + encKey, err := cfca.ParseEscrowPrivateKey(tmpKey, []byte(keydata)) + if err != nil { + panic(err) + } + fmt.Printf("%x\n", encKey.D.Bytes()) + // Output: f6e02c941a0dfdac58d8b3b1bc1bd136f179741b7465ebc7b0b25bb381840a3b +} diff --git a/cfca/pkcs12_sm2.go b/cfca/pkcs12_sm2.go index 0e381f1..19abc08 100644 --- a/cfca/pkcs12_sm2.go +++ b/cfca/pkcs12_sm2.go @@ -58,7 +58,7 @@ func ParseSM2(password, data []byte) (*sm2.PrivateKey, *smx509.Certificate, erro } pk, err := DecryptBySM4CBC(keys.EncryptedKey.EncryptedContent.Bytes, password) if err != nil { - return nil, nil, err + return nil, nil, fmt.Errorf("cfca: failed to decrypt by SM4-CBC, please ensure the password is correct") } prvKey, err := sm2.NewPrivateKeyFromInt(new(big.Int).SetBytes(pk)) if err != nil { diff --git a/cfca/pkcs12_sm2_test.go b/cfca/pkcs12_sm2_test.go index 10e51fa..cfd69bf 100644 --- a/cfca/pkcs12_sm2_test.go +++ b/cfca/pkcs12_sm2_test.go @@ -163,8 +163,8 @@ func TestParseSM2WithInvalidPwd(t *testing.T) { password := []byte("wrongpwd") der, _ := hex.DecodeString("308203490201013047060a2a811ccf55060104020106072a811ccf5501680430016ca58c339f32f5bbe2b0491d5087c9b5de0f5aef4b4d0726941a0c21d9795f51e802f2a1596cc909d1638067ca28cc308202f9060a2a811ccf550601040201048202e9308202e530820289a00302010202051040990809300c06082a811ccf550183750500305c310b300906035504061302434e3130302e060355040a0c274368696e612046696e616e6369616c2043657274696669636174696f6e20417574686f72697479311b301906035504030c1243464341205445535420534d32204f434131301e170d3230313131393038333131385a170d3235313131393038333131385a308189310b300906035504061302434e31173015060355040a0c0e434643412054455354204f434131310d300b060355040b0c045053424331193017060355040b0c104f7267616e697a6174696f6e616c2d323137303506035504030c2e30353140e982aee582a8e7babfe4b88ae694b6e58d95e59586e688b7404e353130313133303030313838373840313059301306072a8648ce3d020106082a811ccf5501822d0342000495510badce29f70be07df6e2b0ce75be124a56c08e82435e72b4aa6c17679f455a6892aadde2a6b7a58ca7b0e10ca78d3811ff27e9f728cd80d53c1b9a6461dba382010630820102301f0603551d230418301680146bfe18da8f423aa6b86db32e88833a34a2c130e1300c0603551d130101ff0402300030480603551d200441303f303d060860811c86ef2a01013031302f06082b060105050702011623687474703a2f2f7777772e636663612e636f6d2e636e2f75732f75732d31342e68746d30390603551d1f04323030302ea02ca02a8628687474703a2f2f7563726c2e636663612e636f6d2e636e2f534d322f63726c31343335362e63726c300e0603551d0f0101ff0404030206c0301d0603551d0e04160414f8863d94f4a13b915ef9321a83a0be23445a7735301d0603551d250416301406082b0601050507030206082b06010505070304300c06082a811ccf5501837505000348003045022100890d2b153df86bfa09c3012323e52cadfa1c6c6a61f280f79c8c22db71d1504202204970b89aeb05e459e3fc2a4d4eabe4f7ee7a16e20d9004c64bcc5187b9332811") _, _, err := ParseSM2(password, der) - if err == nil || err.Error() != "padding: invalid padding byte/length" { - t.Fatal("expected error of padding: invalid padding byte/length") + if err == nil || err.Error() != "cfca: failed to decrypt by SM4-CBC, please ensure the password is correct" { + t.Fatal("cfca: failed to decrypt by SM4-CBC, please ensure the password is correct") } } diff --git a/docs/cfca.md b/docs/cfca.md index cd85578..baf0f6c 100644 --- a/docs/cfca.md +++ b/docs/cfca.md @@ -108,4 +108,4 @@ SADK 3.2之后的版本,支持下列SM2密文格式(encryptedType): 使用`cfca.ParseEscrowPrivateKey`解析CFCA返回的加密用私钥。 ### SM2私钥、证书的解析 -这个是CFCA自定义的,未见相关标准,可以通过```cfca.ParseSM2```来解析。 +这个是CFCA自定义的,未见相关标准,可以通过```cfca.ParseSM2```来解析。```cfca.ParseSM2```函数只接受**DER**编码的二进制数据,如果你的数据是**base64**编码的,请先自行解码。