From af86ca7b7b902dee26aaeb812c03bcb68eda7a9a Mon Sep 17 00:00:00 2001 From: Sun Yimin Date: Tue, 28 Mar 2023 08:41:01 +0800 Subject: [PATCH] pkcs7: enable sign without attributes --- pkcs/cipher.go | 2 +- pkcs/cipher_test.go | 59 +++++++++++++++++++++++++++++++++++++++++++++ pkcs7/sign.go | 15 +++++++----- pkcs7/sign_test.go | 53 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 7 deletions(-) create mode 100644 pkcs/cipher_test.go diff --git a/pkcs/cipher.go b/pkcs/cipher.go index a206c03..6f8ce33 100644 --- a/pkcs/cipher.go +++ b/pkcs/cipher.go @@ -36,7 +36,7 @@ func RegisterCipher(oid asn1.ObjectIdentifier, cipher func() Cipher) { func GetCipher(alg pkix.AlgorithmIdentifier) (Cipher, error) { oid := alg.Algorithm.String() if oid == oidSM4.String() { - if len(alg.Parameters.Bytes) != 0 { + if len(alg.Parameters.Bytes) != 0 || len(alg.Parameters.FullBytes) != 0 { return SM4CBC, nil } else { return SM4ECB, nil diff --git a/pkcs/cipher_test.go b/pkcs/cipher_test.go new file mode 100644 index 0000000..01de947 --- /dev/null +++ b/pkcs/cipher_test.go @@ -0,0 +1,59 @@ +package pkcs + +import ( + "crypto/x509/pkix" + "encoding/asn1" + "testing" +) + +func TestGetCipher(t *testing.T) { + marshalledIV, err := asn1.Marshal([]byte("0123456789ABCDEF")) + if err != nil { + t.Fatal(err) + } + sm4Scheme := pkix.AlgorithmIdentifier{ + Algorithm: oidSM4, + Parameters: asn1.RawValue{FullBytes: marshalledIV}, + } + cipher, err := GetCipher(sm4Scheme) + if err != nil { + t.Fatal(err) + } + if !cipher.OID().Equal(oidSM4CBC) { + t.Errorf("not expected CBC") + } + + _, err = GetCipher(pkix.AlgorithmIdentifier{Algorithm: asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 401, 2}}) + if err == nil || err.Error() != "pkcs: unsupported cipher (OID: 1.2.156.10197.1.401.2)" { + t.Fatal(err) + } +} + +func TestInvalidKeyLen(t *testing.T) { + plaintext := []byte("Hello World") + invalidKey := []byte("123456") + _, _, err := SM4ECB.Encrypt(invalidKey, plaintext) + if err == nil { + t.Errorf("should be error") + } + _, err = SM4ECB.Decrypt(invalidKey, nil, nil) + if err == nil { + t.Errorf("should be error") + } + _, _, err = SM4CBC.Encrypt(invalidKey, plaintext) + if err == nil { + t.Errorf("should be error") + } + _, err = SM4CBC.Decrypt(invalidKey, nil, nil) + if err == nil { + t.Errorf("should be error") + } + _, _, err = SM4GCM.Encrypt(invalidKey, plaintext) + if err == nil { + t.Errorf("should be error") + } + _, err = SM4GCM.Decrypt(invalidKey, nil, nil) + if err == nil { + t.Errorf("should be error") + } +} diff --git a/pkcs7/sign.go b/pkcs7/sign.go index 98586a9..5169ecd 100644 --- a/pkcs7/sign.go +++ b/pkcs7/sign.go @@ -222,7 +222,6 @@ func newHash(hasher crypto.Hash, hashOid asn1.ObjectIdentifier) hash.Hash { return h } -/* // SignWithoutAttr issues a signature on the content of the pkcs7 SignedData. // Unlike AddSigner/AddSignerChain, it calculates the digest on the data alone // and does not include any signed attributes like timestamp and so on. @@ -237,14 +236,19 @@ func (sd *SignedData) SignWithoutAttr(ee *smx509.Certificate, pkey crypto.Privat if err != nil { return err } - h := newHash(hasher, sd.digestOid) - h.Write(sd.data) - sd.messageDigest = h.Sum(nil) key, ok := pkey.(crypto.Signer) if !ok { return errors.New("pkcs7: private key does not implement crypto.Signer") } - signature, err = key.Sign(rand.Reader, sd.messageDigest, nil) + _, isSM2 := pkey.(sm2.Signer) + if isSM2 { + signature, err = key.Sign(rand.Reader, sd.data, sm2.DefaultSM2SignerOpts) + } else { + h := newHash(hasher, sd.digestOid) + h.Write(sd.data) + sd.messageDigest = h.Sum(nil) + signature, err = key.Sign(rand.Reader, sd.messageDigest, hasher) + } if err != nil { return err } @@ -272,7 +276,6 @@ func (sd *SignedData) SignWithoutAttr(ee *smx509.Certificate, pkey crypto.Privat sd.sd.SignerInfos = append(sd.sd.SignerInfos, signer) return nil } -*/ func (si *signerInfo) SetUnauthenticatedAttributes(extraUnsignedAttrs []Attribute) error { unsignedAttrs := &attributes{} diff --git a/pkcs7/sign_test.go b/pkcs7/sign_test.go index 908b871..168d394 100644 --- a/pkcs7/sign_test.go +++ b/pkcs7/sign_test.go @@ -257,3 +257,56 @@ func testOpenSSLParse(t *testing.T, certBytes []byte) { t.Fatal(err) } } + +func TestSignWithoutAttr(t *testing.T) { + content := []byte("Hello World") + sigalgs := []struct { + isSM bool + sigAlg x509.SignatureAlgorithm + }{ + { + false, + x509.SHA256WithRSA, + }, + { + true, + smx509.SM2WithSM3, + }, + } + for _, sigalg := range sigalgs { + cert, err := createTestCertificate(sigalg.sigAlg) + if err != nil { + t.Fatal(err) + } + var toBeSigned *SignedData + if sigalg.isSM { + toBeSigned, err = NewSMSignedData(content) + } else { + toBeSigned, err = NewSignedData(content) + signerDigest, _ := getDigestOIDForSignatureAlgorithm(sigalg.sigAlg) + toBeSigned.SetDigestAlgorithm(signerDigest) + } + if err != nil { + t.Fatalf("Cannot initialize signed data: %s", err) + } + if err := toBeSigned.SignWithoutAttr(cert.Certificate, *cert.PrivateKey, SignerInfoConfig{}); err != nil { + t.Fatalf("Cannot add signer: %s", err) + } + signed, err := toBeSigned.Finish() + if err != nil { + t.Fatalf("Cannot finish signing data: %s", err) + } + p7, err := Parse(signed) + if err != nil { + t.Fatalf("Cannot parse signed data: %v", err) + } + if len(p7.Certificates) == 0 { + t.Errorf("No certificates") + } + + err = p7.Verify() + if err != nil { + t.Fatal(err) + } + } +}