github.com/emmansun/gmsm@v0.29.1/pkcs7/sign_test.go (about) 1 package pkcs7 2 3 import ( 4 "bytes" 5 "crypto/x509" 6 "encoding/asn1" 7 "encoding/pem" 8 "fmt" 9 "io/ioutil" 10 "log" 11 "os" 12 "os/exec" 13 "testing" 14 15 "github.com/emmansun/gmsm/smx509" 16 ) 17 18 func testSign(t *testing.T, isSM bool, content []byte, sigalgs []x509.SignatureAlgorithm) { 19 for _, sigalgroot := range sigalgs { 20 rootCert, err := createTestCertificateByIssuer("PKCS7 Test Root CA", nil, sigalgroot, true) 21 if err != nil { 22 t.Fatalf("test %s: cannot generate root cert: %s", sigalgroot, err) 23 } 24 truststore := smx509.NewCertPool() 25 truststore.AddCert(rootCert.Certificate) 26 for _, sigalginter := range sigalgs { 27 interCert, err := createTestCertificateByIssuer("PKCS7 Test Intermediate Cert", rootCert, sigalginter, true) 28 if err != nil { 29 t.Fatalf("test %s/%s: cannot generate intermediate cert: %s", sigalgroot, sigalginter, err) 30 } 31 var parents []*smx509.Certificate 32 parents = append(parents, interCert.Certificate) 33 for _, sigalgsigner := range sigalgs { 34 signerCert, err := createTestCertificateByIssuer("PKCS7 Test Signer Cert", interCert, sigalgsigner, false) 35 if err != nil { 36 t.Fatalf("test %s/%s/%s: cannot generate signer cert: %s", sigalgroot, sigalginter, sigalgsigner, err) 37 } 38 for _, testDetach := range []bool{false, true} { 39 log.Printf("test %s/%s/%s detached %t\n", sigalgroot, sigalginter, sigalgsigner, testDetach) 40 var toBeSigned *SignedData 41 if isSM { 42 toBeSigned, err = NewSMSignedData(content) 43 } else { 44 toBeSigned, err = NewSignedData(content) 45 } 46 if err != nil { 47 t.Fatalf("test %s/%s/%s: cannot initialize signed data: %s", sigalgroot, sigalginter, sigalgsigner, err) 48 } 49 50 // Set the digest to match the end entity cert 51 signerDigest, _ := getDigestOIDForSignatureAlgorithm(sigalgsigner) 52 toBeSigned.SetDigestAlgorithm(signerDigest) 53 54 if err := toBeSigned.AddSignerChain(signerCert.Certificate, *signerCert.PrivateKey, parents, SignerInfoConfig{}); err != nil { 55 t.Fatalf("test %s/%s/%s: cannot add signer: %s", sigalgroot, sigalginter, sigalgsigner, err) 56 } 57 if testDetach { 58 toBeSigned.Detach() 59 } 60 signed, err := toBeSigned.Finish() 61 if err != nil { 62 t.Fatalf("test %s/%s/%s: cannot finish signing data: %s", sigalgroot, sigalginter, sigalgsigner, err) 63 } 64 pem.Encode(os.Stdout, &pem.Block{Type: "PKCS7", Bytes: signed}) 65 p7, err := Parse(signed) 66 if err != nil { 67 t.Fatalf("test %s/%s/%s: cannot parse signed data: %s", sigalgroot, sigalginter, sigalgsigner, err) 68 } 69 if testDetach { 70 // Detached signature should not contain the content 71 // So we should not be able to find the content in the parsed data 72 // We should suppliment the content to the parsed data before verifying 73 p7.Content = content 74 } 75 if !bytes.Equal(content, p7.Content) { 76 t.Errorf("test %s/%s/%s: content was not found in the parsed data:\n\tExpected: %s\n\tActual: %s", sigalgroot, sigalginter, sigalgsigner, content, p7.Content) 77 } 78 if err := p7.VerifyWithChain(truststore); err != nil { 79 t.Errorf("test %s/%s/%s: cannot verify signed data: %s", sigalgroot, sigalginter, sigalgsigner, err) 80 } 81 if !signerDigest.Equal(p7.Signers[0].DigestAlgorithm.Algorithm) { 82 t.Errorf("test %s/%s/%s: expected digest algorithm %q but got %q", 83 sigalgroot, sigalginter, sigalgsigner, signerDigest, p7.Signers[0].DigestAlgorithm.Algorithm) 84 } 85 } 86 } 87 } 88 } 89 } 90 func TestSign(t *testing.T) { 91 content := []byte("Hello World") 92 sigalgs := []x509.SignatureAlgorithm{ 93 x509.SHA1WithRSA, 94 x509.SHA256WithRSA, 95 x509.SHA512WithRSA, 96 x509.ECDSAWithSHA1, 97 x509.ECDSAWithSHA256, 98 x509.ECDSAWithSHA384, 99 x509.ECDSAWithSHA512, 100 smx509.SM2WithSM3, 101 } 102 testSign(t, false, content, sigalgs) 103 } 104 105 func TestSignSM(t *testing.T) { 106 content := []byte("Hello World") 107 sigalgs := []x509.SignatureAlgorithm{ 108 smx509.SM2WithSM3, 109 } 110 testSign(t, true, content, sigalgs) 111 } 112 113 func ExampleSignedData() { 114 // generate a signing cert or load a key pair 115 cert, err := createTestCertificate(x509.SHA256WithRSA) 116 if err != nil { 117 fmt.Printf("Cannot create test certificates: %s", err) 118 } 119 120 // Initialize a SignedData struct with content to be signed 121 signedData, err := NewSignedData([]byte("Example data to be signed")) 122 if err != nil { 123 fmt.Printf("Cannot initialize signed data: %s", err) 124 } 125 126 // Add the signing cert and private key 127 if err := signedData.AddSigner(cert.Certificate, cert.PrivateKey, SignerInfoConfig{}); err != nil { 128 fmt.Printf("Cannot add signer: %s", err) 129 } 130 131 // Call Detach() is you want to remove content from the signature 132 // and generate an S/MIME detached signature 133 signedData.Detach() 134 135 // Finish() to obtain the signature bytes 136 detachedSignature, err := signedData.Finish() 137 if err != nil { 138 fmt.Printf("Cannot finish signing data: %s", err) 139 } 140 pem.Encode(os.Stdout, &pem.Block{Type: "PKCS7", Bytes: detachedSignature}) 141 } 142 143 func TestUnmarshalSignedAttribute(t *testing.T) { 144 cert, err := createTestCertificate(x509.SHA512WithRSA) 145 if err != nil { 146 t.Fatal(err) 147 } 148 content := []byte("Hello World") 149 toBeSigned, err := NewSignedData(content) 150 if err != nil { 151 t.Fatalf("Cannot initialize signed data: %s", err) 152 } 153 oidTest := asn1.ObjectIdentifier{2, 3, 4, 5, 6, 7} 154 testValue := "TestValue" 155 if err := toBeSigned.AddSigner(cert.Certificate, *cert.PrivateKey, SignerInfoConfig{ 156 ExtraSignedAttributes: []Attribute{{Type: oidTest, Value: testValue}}, 157 }); err != nil { 158 t.Fatalf("Cannot add signer: %s", err) 159 } 160 signed, err := toBeSigned.Finish() 161 if err != nil { 162 t.Fatalf("Cannot finish signing data: %s", err) 163 } 164 p7, err := Parse(signed) 165 if err != nil { 166 t.Fatalf("Cannot parse signed data: %v", err) 167 } 168 var actual string 169 err = p7.UnmarshalSignedAttribute(oidTest, &actual) 170 if err != nil { 171 t.Fatalf("Cannot unmarshal test value: %s", err) 172 } 173 if testValue != actual { 174 t.Errorf("Attribute does not match test value\n\tExpected: %s\n\tActual: %s", testValue, actual) 175 } 176 err = p7.Verify() 177 if err != nil { 178 t.Fatal(err) 179 } 180 } 181 182 func TestSkipCertificates(t *testing.T) { 183 cert, err := createTestCertificate(x509.SHA512WithRSA) 184 if err != nil { 185 t.Fatal(err) 186 } 187 content := []byte("Hello World") 188 toBeSigned, err := NewSignedData(content) 189 if err != nil { 190 t.Fatalf("Cannot initialize signed data: %s", err) 191 } 192 193 if err := toBeSigned.AddSigner(cert.Certificate, *cert.PrivateKey, SignerInfoConfig{}); err != nil { 194 t.Fatalf("Cannot add signer: %s", err) 195 } 196 signed, err := toBeSigned.Finish() 197 if err != nil { 198 t.Fatalf("Cannot finish signing data: %s", err) 199 } 200 p7, err := Parse(signed) 201 if err != nil { 202 t.Fatalf("Cannot parse signed data: %v", err) 203 } 204 if len(p7.Certificates) == 0 { 205 t.Errorf("No certificates") 206 } 207 208 toBeSigned2, err := NewSignedData(content) 209 if err != nil { 210 t.Fatalf("Cannot initialize signed data: %s", err) 211 } 212 if err := toBeSigned2.AddSigner(cert.Certificate, *cert.PrivateKey, SignerInfoConfig{SkipCertificates: true}); err != nil { 213 t.Fatalf("Cannot add signer: %s", err) 214 } 215 signed, err = toBeSigned2.Finish() 216 if err != nil { 217 t.Fatalf("Cannot finish signing data: %s", err) 218 } 219 p7, err = Parse(signed) 220 if err != nil { 221 t.Fatalf("Cannot parse signed data: %v", err) 222 } 223 if len(p7.Certificates) > 0 { 224 t.Errorf("Have certificates: %v", p7.Certificates) 225 } 226 // For skip certificates, we should not be able to verify the signature 227 // because the signer certificate is not in the chain 228 // we should suppliment the signer certificate to the parsed data before verifying 229 p7.Certificates = append(p7.Certificates, cert.Certificate) 230 err = p7.Verify() 231 if err != nil { 232 t.Fatal(err) 233 } 234 } 235 236 func TestDegenerateCertificate(t *testing.T) { 237 cert, err := createTestCertificate(x509.SHA1WithRSA) 238 if err != nil { 239 t.Fatal(err) 240 } 241 deg, err := DegenerateCertificate(cert.Certificate.Raw) 242 if err != nil { 243 t.Fatal(err) 244 } 245 testOpenSSLParse(t, deg) 246 pem.Encode(os.Stdout, &pem.Block{Type: "PKCS7", Bytes: deg}) 247 } 248 249 // writes the cert to a temporary file and tests that openssl can read it. 250 func testOpenSSLParse(t *testing.T, certBytes []byte) { 251 tmpCertFile, err := ioutil.TempFile("", "testCertificate") 252 if err != nil { 253 t.Fatal(err) 254 } 255 defer os.Remove(tmpCertFile.Name()) // clean up 256 257 if _, err := tmpCertFile.Write(certBytes); err != nil { 258 t.Fatal(err) 259 } 260 261 opensslCMD := exec.Command("openssl", "pkcs7", "-inform", "der", "-in", tmpCertFile.Name()) 262 _, err = opensslCMD.Output() 263 if err != nil { 264 t.Fatal(err) 265 } 266 267 if err := tmpCertFile.Close(); err != nil { 268 t.Fatal(err) 269 } 270 } 271 272 func TestSignWithoutAttr(t *testing.T) { 273 content := []byte("Hello World") 274 sigalgs := []struct { 275 isSM bool 276 sigAlg x509.SignatureAlgorithm 277 skipCert bool 278 }{ 279 { 280 false, 281 x509.SHA256WithRSA, 282 false, 283 }, 284 { 285 true, 286 smx509.SM2WithSM3, 287 false, 288 }, 289 { 290 false, 291 x509.SHA256WithRSA, 292 true, 293 }, 294 { 295 true, 296 smx509.SM2WithSM3, 297 true, 298 }, 299 } 300 for _, sigalg := range sigalgs { 301 cert, err := createTestCertificate(sigalg.sigAlg) 302 if err != nil { 303 t.Fatal(err) 304 } 305 var toBeSigned *SignedData 306 if sigalg.isSM { 307 toBeSigned, err = NewSMSignedData(content) 308 } else { 309 toBeSigned, err = NewSignedData(content) 310 signerDigest, _ := getDigestOIDForSignatureAlgorithm(sigalg.sigAlg) 311 toBeSigned.SetDigestAlgorithm(signerDigest) 312 } 313 if err != nil { 314 t.Fatalf("Cannot initialize signed data: %s", err) 315 } 316 if err := toBeSigned.SignWithoutAttr(cert.Certificate, *cert.PrivateKey, SignerInfoConfig{SkipCertificates: sigalg.skipCert}); err != nil { 317 t.Fatalf("Cannot add signer: %s", err) 318 } 319 signed, err := toBeSigned.Finish() 320 if err != nil { 321 t.Fatalf("Cannot finish signing data: %s", err) 322 } 323 p7, err := Parse(signed) 324 if err != nil { 325 t.Fatalf("Cannot parse signed data: %v", err) 326 } 327 if !sigalg.skipCert { 328 if len(p7.Certificates) == 0 { 329 t.Errorf("No certificates") 330 } 331 err = p7.Verify() 332 if err != nil { 333 t.Fatal(err) 334 } 335 } else { 336 if len(p7.Certificates) > 0 { 337 t.Errorf("No certificates expected") 338 } 339 err = p7.Verify() 340 if sigalg.skipCert && err.Error() != "pkcs7: No certificate for signer" { 341 t.Fatalf("Expected pkcs7: No certificate for signer") 342 } 343 p7.Certificates = append(p7.Certificates, cert.Certificate) 344 err = p7.Verify() 345 if err != nil { 346 t.Fatal(err) 347 } 348 } 349 } 350 }