cfca

package
v0.29.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 26, 2025 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package cfca supports part of CFCA SADK's functions, provides interoperability with CFCA SADK.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func CreateCertificateRequest added in v0.29.6

func CreateCertificateRequest(rand io.Reader, template *x509.CertificateRequest, certPriv, tmpPub any, challengePassword string) ([]byte, error)

CreateCertificateRequest creates a new certificate request based on a template. The following members of template are used: Subject. The certPriv is the private key for the certificate, and the tmpPub is the temporary public key for returning encryption key decryption. The challenge password is basically a shared-secret nonce between you and CFCA, embedded in the CSR.

Example
package main

import (
	"crypto/ecdsa"
	"crypto/rand"
	"crypto/x509"
	"crypto/x509/pkix"

	"encoding/hex"

	"fmt"

	"github.com/emmansun/gmsm/cfca"
	"github.com/emmansun/gmsm/sm2"
)

func main() {
	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 DecryptBySM4CBC added in v0.29.6

func DecryptBySM4CBC(ciphertext, password []byte) ([]byte, error)

DecryptBySM4CBC decrypts the data with the password using SM4-CBC algorithm. Corresponds to the cfca.sadk.util.decryptMessageBySM4 method.

func EncryptBySM4CBC added in v0.29.6

func EncryptBySM4CBC(plaintext, password []byte) ([]byte, error)

EncryptBySM4CBC encrypts the data with the password using SM4-CBC algorithm. Corresponds to the cfca.sadk.util.encryptMessageBySM4 method.

func EnvelopeMessage added in v0.29.5

func EnvelopeMessage(cipher pkcs.Cipher, content []byte, recipients []*smx509.Certificate) ([]byte, error)

EnvelopeMessage creates and returns an envelope data PKCS7 structure (DER encoded) with encrypted recipient keys for each recipient public key.

The OIDs use GM/T 0010 - 2012 set and the encrypted key uses ASN.1 format. This function uses recipient's SubjectKeyIdentifier to identify the recipient.

func EnvelopeMessageLegacy added in v0.29.5

func EnvelopeMessageLegacy(cipher pkcs.Cipher, content []byte, recipients []*smx509.Certificate) ([]byte, error)

EnvelopeMessageLegacy creates and returns an envelope data PKCS7 structure (DER encoded) with encrypted recipient keys for each recipient public key. This method is used for CFCA SADK verion less than 3.2 compatibility.

The OIDs use GM/T 0010 - 2012 set and the encrypted key use C1C2C3 format and without 0x4 prefix. This function uses recipient's IssuerAndSerialNumber to identify the recipient.

func MarshalSM2

func MarshalSM2(password []byte, key *sm2.PrivateKey, cert *smx509.Certificate) ([]byte, error)

MarshalSM2 encodes sm2 private key and related certificate to cfca defined format. This method is corresponding to CFCA SADK's cfca.sadk.asn1.pkcs.CombineSM2Data.

Example (ChangePassword)
package main

import (
	"encoding/pem"
	"fmt"

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

func main() {
	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 NewSM4CBCBlockMode added in v0.29.6

func NewSM4CBCBlockMode(password []byte, isEncrypter bool) (cipher.BlockMode, error)

NewSM4CBCBlockMode creates a new SM4-CBC block mode with the password.

func OpenEnvelopedMessage added in v0.29.5

func OpenEnvelopedMessage(data []byte, recipientCert *smx509.Certificate, key crypto.PrivateKey) ([]byte, error)

OpenEnvelopedMessage decrypts the enveloped message (DER encoded) using the provided certificate and private key. The certificate is used to identify the recipient and the private key is used to decrypt the encrypted key.

func OpenEnvelopedMessageLegacy added in v0.29.5

func OpenEnvelopedMessageLegacy(data []byte, recipientCert *smx509.Certificate, key crypto.PrivateKey) ([]byte, error)

OpenEnvelopedMessageLegacy decrypts the enveloped message (DER encoded) using the provided certificate and private key. The certificate is used to identify the recipient and the private key is used to decrypt the encrypted key.

This method is used for CFCA SADK verion less than 3.2 compatibility.

func ParseEscrowPrivateKey added in v0.29.6

func ParseEscrowPrivateKey(tmpPriv *sm2.PrivateKey, data []byte) (*sm2.PrivateKey, error)

ParseEscrowPrivateKey parses an CFCA generated and returned SM2 private key from the given data. The data is expected to be in the format of "0000000000000001000000000000000100000000000000000000000000000000...". If the data is not in this format, it will be treated as base64 encoded data directly.

Example
package main

import (
	"encoding/hex"

	"fmt"

	"github.com/emmansun/gmsm/cfca"
	"github.com/emmansun/gmsm/sm2"
)

func main() {
	// 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

func ParseSM2

func ParseSM2(password, data []byte) (*sm2.PrivateKey, *smx509.Certificate, error)

ParseSM2 parses the der data, returns private key and related certificate, it's CFCA private structure. This method is corresponding to CFCA SADK's cfca.sadk.asn1.pkcs.load.

Example
package main

import (
	"encoding/base64"

	"fmt"

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

func main() {
	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
Example (PemEncoded)
package main

import (
	"encoding/pem"
	"fmt"

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

func main() {
	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 SignDigestDetach added in v0.29.7

func SignDigestDetach(digest []byte, cert *smx509.Certificate, key crypto.PrivateKey) ([]byte, error)

SignDigestDetach signs a given digest using the provided certificate and private key, and returns the detached PKCS7 signature.

This method corresponds to CFCA SADK's cfca.sadk.util.p7SignByHash.

func SignMessageAttach added in v0.29.6

func SignMessageAttach(data []byte, cert *smx509.Certificate, key crypto.PrivateKey) ([]byte, error)

SignMessageAttach signs the data with the certificate and private key, returns the signed data in PKCS7 (DER) format. This method corresponds to CFCA SADK's cfca.sadk.util.p7SignMessageAttach.

func SignMessageDetach added in v0.29.6

func SignMessageDetach(data []byte, cert *smx509.Certificate, key crypto.PrivateKey) ([]byte, error)

SignMessageDetach signs the data with the certificate and private key, returns the signed data in PKCS7 (DER) format. This method corresponds to CFCA SADK's cfca.sadk.util.p7SignMessageDetach.

func VerifyDigestDetach added in v0.29.7

func VerifyDigestDetach(p7Der, digest []byte) error

VerifyDigestDetach verifies a detached PKCS7 signature against a given digest. It parses the p7Der, assigns the provided digest to the parsed PKCS7 content, and then verifies it.

This method corresponds to CFCA SADK's cfca.sadk.util.p7VerifyByHash.

func VerifyMessageAttach added in v0.29.6

func VerifyMessageAttach(p7Der []byte) error

VerifyMessageAttach verifies the signed data in PKCS7 (DER) format. This method corresponds to CFCA SADK's cfca.sadk.util.p7VerifyMessageAttach. If verification fails, an error is returned. otherwise, nil is returned.

func VerifyMessageDetach added in v0.29.6

func VerifyMessageDetach(p7Der, sourceData []byte) error

VerifyMessageDetach verifies the signed data in PKCS7 (DER) format with the given source data. This method corresponds to CFCA SADK's cfca.sadk.util.p7VerifyMessageDetach. If verification fails, an error is returned. otherwise, nil is returned.

Types

type CertificateRequest added in v0.29.6

type CertificateRequest = smx509.CertificateRequestCFCA

func ParseCertificateRequest added in v0.29.6

func ParseCertificateRequest(der []byte) (*CertificateRequest, error)

ParseCertificateRequest parses a certificate request from the given DER data. This method corresponds to CFCA SADK's cfca.sadk.asn1.pkcs.PKCS10.load.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL