diff --git a/cryptobin/ca/ca.go b/cryptobin/ca/ca.go index 6cc2055..5616a22 100644 --- a/cryptobin/ca/ca.go +++ b/cryptobin/ca/ca.go @@ -65,7 +65,7 @@ type CA struct { // 证书数据 cert *x509.Certificate - // 证书请求 + // 请求证书 certRequest *x509.CertificateRequest // 私钥 diff --git a/cryptobin/ca/ca_test.go b/cryptobin/ca/ca_test.go index 35b5a08..ec2b01f 100644 --- a/cryptobin/ca/ca_test.go +++ b/cryptobin/ca/ca_test.go @@ -1,16 +1,50 @@ package ca import ( + "net" + "errors" "testing" "encoding/pem" + "crypto/dsa" + "crypto/rsa" + "crypto/rand" + "crypto/x509" "crypto/x509/pkix" + "crypto/elliptic" cryptobin_x509 "github.com/deatil/go-cryptobin/x509" cryptobin_test "github.com/deatil/go-cryptobin/tool/test" ) +func Test_To(t *testing.T) { + assertEqual := cryptobin_test.AssertEqualT(t) + + testssh := New() + testssh.keyData = []byte("test") + + assertEqual(testssh.ToKeyBytes(), []byte("test"), "Test_OnError Error") + assertEqual(testssh.ToKeyString(), "test", "Test_OnError Error") +} + +func Test_OnError(t *testing.T) { + assertEqual := cryptobin_test.AssertEqualT(t) + + err := errors.New("test-error") + + testssh := New() + testssh.Errors = append(testssh.Errors, err) + + testssh = testssh.OnError(func(errs []error) { + assertEqual(errs, []error{err}, "Test_OnError") + }) + + err2 := testssh.Error().Error() + assertEqual(err2, err.Error(), "Test_OnError Error") +} + func Test_CreateCA(t *testing.T) { assertError := cryptobin_test.AssertErrorT(t) + assertEqual := cryptobin_test.AssertEqualT(t) assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) obj := New(). @@ -20,16 +54,27 @@ func Test_CreateCA(t *testing.T) { MakeCA(pkix.Name{ CommonName: "test.example.com", Organization: []string{"Test Organization"}, - }, 2, "SHA256WithRSA"). - CreateCA() - key := obj.ToKeyString() + }, 2, "SHA256WithRSA") + + ca := obj.CreateCA().ToKeyString() + prikey := obj.CreatePrivateKey().ToKeyString() assertError(obj.Error(), "Test_CreateCA") - assertNotEmpty(key, "Test_CreateCA") + assertNotEmpty(ca, "Test_CreateCA-ca") + assertNotEmpty(prikey, "Test_CreateCA-prikey") // =========== - block, _ := pem.Decode([]byte(key)) + // Parse Certificate PEM + parsePubkey := New(). + FromCertificate([]byte(ca)). + GetPublicKey() + + assertEqual(parsePubkey, obj.GetPublicKey(), "Test_CreateCA") + + // =========== + + block, _ := pem.Decode([]byte(ca)) if block == nil { t.Fatal("failed to read cert") } @@ -45,8 +90,191 @@ func Test_CreateCA(t *testing.T) { } } +func Test_CreateCAWithIssuer(t *testing.T) { + assertError := cryptobin_test.AssertErrorT(t) + assertEqual := cryptobin_test.AssertEqualT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + + obj := New(). + SetPublicKeyType("RSA"). + WithBits(512). + GenerateKey(). + MakeCA(pkix.Name{ + CommonName: "test.example.com", + Organization: []string{"Test Organization"}, + }, 2, "SHA256WithRSA") + + root := obj.CreateCA().ToKeyString() + prikey := obj.CreatePrivateKey().ToKeyString() + + assertError(obj.Error(), "Test_CreateCAWithIssuer") + assertNotEmpty(root, "Test_CreateCAWithIssuer-root") + assertNotEmpty(prikey, "Test_CreateCAWithIssuer-prikey") + + // =========== + + obj2 := New(). + SetPublicKeyType("RSA"). + WithBits(512). + GenerateKey(). + MakeCA(pkix.Name{ + CommonName: "test22.example.com", + Organization: []string{"Test22 Organization"}, + }, 3, "SHA256WithRSA"). + CreateCAWithIssuer(obj.GetCert(), obj.GetPrivateKey()) + ca := obj2.ToKeyString() + + assertError(obj2.Error(), "Test_CreateCAWithIssuer-CreateCert") + assertNotEmpty(ca, "Test_CreateCAWithIssuer-CreateCert") + + // =========== + + // Parse Certificate PEM + parsePubkey := New(). + FromCertificate([]byte(ca)). + GetPublicKey() + + assertEqual(parsePubkey, obj2.GetPublicKey(), "Test_CreateCAWithIssuer") +} + +func Test_CreateCert(t *testing.T) { + assertError := cryptobin_test.AssertErrorT(t) + assertEqual := cryptobin_test.AssertEqualT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + + obj := New(). + SetPublicKeyType("RSA"). + WithBits(512). + GenerateKey(). + MakeCA(pkix.Name{ + CommonName: "test.example.com", + Organization: []string{"Test Organization"}, + }, 2, "SHA256WithRSA") + + ca := obj.CreateCA().ToKeyString() + prikey := obj.CreatePrivateKey().ToKeyString() + + assertError(obj.Error(), "Test_CreateCert") + assertNotEmpty(ca, "Test_CreateCert") + assertNotEmpty(prikey, "Test_CreateCert-prikey") + + // =========== + + obj2 := New(). + SetPublicKeyType("RSA"). + WithBits(512). + GenerateKey(). + MakeCert(pkix.Name{ + CommonName: "test.example.com", + Organization: []string{"Test Organization"}, + Country: []string{"China"}, + }, 2, []string{ + "test.example.com", + }, []net.IP{ + net.IPv4(127, 0, 0, 1).To4(), + net.ParseIP("2001:4860:0:2001::68"), + }, "SHA256WithRSA"). + CreateCert(obj.GetCert(), obj.GetPrivateKey()) + cert := obj2.ToKeyString() + + assertError(obj2.Error(), "Test_CreateCert-CreateCert") + assertNotEmpty(cert, "Test_CreateCert-CreateCert") + + // =========== + + // Parse Certificate PEM + parsePubkey := New(). + FromCertificate([]byte(cert)). + GetPublicKey() + + assertEqual(parsePubkey, obj2.GetPublicKey(), "Test_CreateCert") +} + +func Test_CreateCSR(t *testing.T) { + assertError := cryptobin_test.AssertErrorT(t) + assertEqual := cryptobin_test.AssertEqualT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + + obj := New(). + SetPublicKeyType("RSA"). + WithBits(512). + GenerateKey(). + MakeCSR( + "test.example.com", + []string{"Test"}, + "SHA256WithRSA", + ) + + cert0 := obj.CreateCSR().ToKeyString() + prikey := obj.CreatePrivateKey().ToKeyString() + + assertError(obj.Error(), "Test_CreateCSR") + assertNotEmpty(cert0, "Test_CreateCSR") + assertNotEmpty(prikey, "Test_CreateCSR-prikey") + + // =========== + + // Parse Certificate PEM + parsePubkey := New(). + FromCertificateRequest([]byte(cert0)). + GetPublicKey() + + assertEqual(parsePubkey, obj.GetPublicKey(), "Test_CreateCSR") + + // =========== + + block, _ := pem.Decode([]byte(cert0)) + if block == nil { + t.Fatal("failed to read cert") + } + + cert, err := cryptobin_x509.ParseCertificateRequest(block.Bytes) + if err != nil { + t.Fatal("failed to read cert file") + } + + err = cert.CheckSignature() + if err != nil { + t.Fatal(err) + } +} + +func Test_UpdateCert(t *testing.T) { + assertEqual := cryptobin_test.AssertEqualT(t) + + obj := New(). + MakeCA(pkix.Name{ + CommonName: "test.example.com", + Organization: []string{"Test Organization"}, + }, 2, "SHA256WithRSA"). + UpdateCert(func(cert *cryptobin_x509.Certificate) { + cert.SubjectKeyId = []byte{1, 2, 3, 4, 6, 7} + }). + GetCert() + + assertEqual(obj.SubjectKeyId, []byte{1, 2, 3, 4, 6, 7}, "Test_UpdateCert") +} + +func Test_UpdateCertRequest(t *testing.T) { + assertEqual := cryptobin_test.AssertEqualT(t) + + obj := New(). + MakeCSR( + "test.example.com", + []string{"Test"}, + "SHA256WithRSA", + ). + UpdateCertRequest(func(cert *cryptobin_x509.CertificateRequest) { + cert.Subject.CommonName = "test11.example.com" + }). + GetCertRequest() + + assertEqual(obj.Subject.CommonName, "test11.example.com", "Test_UpdateCertRequest") +} + func Test_GenerateKey(t *testing.T) { assertError := cryptobin_test.AssertErrorT(t) + assertEqual := cryptobin_test.AssertEqualT(t) assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) t.Run("GenerateRSAKey", func(t *testing.T) { @@ -66,6 +294,22 @@ func Test_GenerateKey(t *testing.T) { prikey2 := obj.CreatePrivateKeyWithPassword(pass).ToKeyString() assertNotEmpty(prikey2, "Test_GenerateKey-prikey2") + + prikey22 := New(). + FromPrivateKey([]byte(prikey)). + GetPrivateKey() + assertEqual(prikey22, obj.GetPrivateKey(), "Test_GenerateKey-FromPrivateKey") + + prikey223 := New(). + FromPrivateKeyWithPassword([]byte(prikey2), pass). + GetPrivateKey() + assertEqual(prikey223, obj.GetPrivateKey(), "Test_GenerateKey-FromPrivateKeyWithPassword") + + pubkey22 := New(). + FromPublicKey([]byte(pubkey)). + GetPublicKey() + assertEqual(pubkey22, obj.GetPublicKey(), "Test_GenerateKey-FromPublicKey") + }) t.Run("GenerateDSAKey", func(t *testing.T) { @@ -85,6 +329,21 @@ func Test_GenerateKey(t *testing.T) { prikey2 := obj.CreatePrivateKeyWithPassword(pass).ToKeyString() assertNotEmpty(prikey2, "Test_GenerateKey-prikey2") + + prikey22 := New(). + FromPrivateKey([]byte(prikey)). + GetPrivateKey() + assertEqual(prikey22, obj.GetPrivateKey(), "Test_GenerateKey-FromPrivateKey") + + prikey223 := New(). + FromPrivateKeyWithPassword([]byte(prikey2), pass). + GetPrivateKey() + assertEqual(prikey223, obj.GetPrivateKey(), "Test_GenerateKey-FromPrivateKeyWithPassword") + + pubkey22 := New(). + FromPublicKey([]byte(pubkey)). + GetPublicKey() + assertEqual(pubkey22, obj.GetPublicKey(), "Test_GenerateKey-FromPublicKey") }) t.Run("GenerateECDSAKey", func(t *testing.T) { @@ -104,6 +363,21 @@ func Test_GenerateKey(t *testing.T) { prikey2 := obj.CreatePrivateKeyWithPassword(pass).ToKeyString() assertNotEmpty(prikey2, "Test_GenerateKey-prikey2") + + prikey22 := New(). + FromPrivateKey([]byte(prikey)). + GetPrivateKey() + assertEqual(prikey22, obj.GetPrivateKey(), "Test_GenerateKey-FromPrivateKey") + + prikey223 := New(). + FromPrivateKeyWithPassword([]byte(prikey2), pass). + GetPrivateKey() + assertEqual(prikey223, obj.GetPrivateKey(), "Test_GenerateKey-FromPrivateKeyWithPassword") + + pubkey22 := New(). + FromPublicKey([]byte(pubkey)). + GetPublicKey() + assertEqual(pubkey22, obj.GetPublicKey(), "Test_GenerateKey-FromPublicKey") }) t.Run("GenerateEdDSAKey", func(t *testing.T) { @@ -122,6 +396,21 @@ func Test_GenerateKey(t *testing.T) { prikey2 := obj.CreatePrivateKeyWithPassword(pass).ToKeyString() assertNotEmpty(prikey2, "Test_GenerateKey-prikey2") + + prikey22 := New(). + FromPrivateKey([]byte(prikey)). + GetPrivateKey() + assertEqual(prikey22, obj.GetPrivateKey(), "Test_GenerateKey-FromPrivateKey") + + prikey223 := New(). + FromPrivateKeyWithPassword([]byte(prikey2), pass). + GetPrivateKey() + assertEqual(prikey223, obj.GetPrivateKey(), "Test_GenerateKey-FromPrivateKeyWithPassword") + + pubkey22 := New(). + FromPublicKey([]byte(pubkey)). + GetPublicKey() + assertEqual(pubkey22, obj.GetPublicKey(), "Test_GenerateKey-FromPublicKey") }) t.Run("GenerateSM2Key", func(t *testing.T) { @@ -140,6 +429,21 @@ func Test_GenerateKey(t *testing.T) { prikey2 := obj.CreatePrivateKeyWithPassword(pass).ToKeyString() assertNotEmpty(prikey2, "Test_GenerateKey-prikey2") + + prikey22 := New(). + FromPrivateKey([]byte(prikey)). + GetPrivateKey() + assertEqual(prikey22, obj.GetPrivateKey(), "Test_GenerateKey-FromPrivateKey") + + prikey223 := New(). + FromPrivateKeyWithPassword([]byte(prikey2), pass). + GetPrivateKey() + assertEqual(prikey223, obj.GetPrivateKey(), "Test_GenerateKey-FromPrivateKeyWithPassword") + + pubkey22 := New(). + FromPublicKey([]byte(pubkey)). + GetPublicKey() + assertEqual(pubkey22, obj.GetPublicKey(), "Test_GenerateKey-FromPublicKey") }) t.Run("GenerateRSAKey 2", func(t *testing.T) { @@ -159,6 +463,21 @@ func Test_GenerateKey(t *testing.T) { prikey2 := obj.CreatePrivateKeyWithPassword(pass).ToKeyString() assertNotEmpty(prikey2, "Test_GenerateKey-prikey2") + + prikey22 := New(). + FromPrivateKey([]byte(prikey)). + GetPrivateKey() + assertEqual(prikey22, obj.GetPrivateKey(), "Test_GenerateKey-FromPrivateKey") + + prikey223 := New(). + FromPrivateKeyWithPassword([]byte(prikey2), pass). + GetPrivateKey() + assertEqual(prikey223, obj.GetPrivateKey(), "Test_GenerateKey-FromPrivateKeyWithPassword") + + pubkey22 := New(). + FromPublicKey([]byte(pubkey)). + GetPublicKey() + assertEqual(pubkey22, obj.GetPublicKey(), "Test_GenerateKey-FromPublicKey") }) } @@ -227,3 +546,272 @@ func Test_GenerateKey2(t *testing.T) { }) } + +var prikey = ` +-----BEGIN PRIVATE KEY----- +MIIBVgIBADANBgkqhkiG9w0BAQEFAASCAUAwggE8AgEAAkEAshKL2U6CuLgNBmNs +SQNDrXbSbRNT8ZoyIEmijQ2mlkfxKbW8l5D83m41x+6Ml69t2hgJnHkg9rFHgf33 +gyxlZwIDAQABAkA8IJkKIkFvf+4d9xpMOQb0HogE/p68mLVOQ67YdACJA2dSrWt6 +BRuMS/09YgTnACqCg+iazLEyuPbPjUO1vijRAiEAyWEzF4as13nXSVkB//EWfTTx +gZHvdDeRq6VVWqPHpxkCIQDiXwIg0i7ZXCBxrOHPflaQwdvX9b7m0Ng2mL0qwrSA +fwIhAIWj/6gJNAL7VKfUbcNQV0BYNj1qf6J8jit+2RoBvqlhAiEAqBRtSxtk58VM +3brFC8C928vlRWvVbCKDd75fLuHVDlcCIQCNnCqes/3rG/wW7XTSNUWWYV5vTasb +I8MfrrxWD1Rkiw== +-----END PRIVATE KEY----- +` + +var ca = ` +-----BEGIN CERTIFICATE----- +MIIBpDCCAU6gAwIBAgIEWrCvfjANBgkqhkiG9w0BAQsFADA3MRowGAYDVQQKExFU +ZXN0IE9yZ2FuaXphdGlvbjEZMBcGA1UEAxMQdGVzdC5leGFtcGxlLmNvbTAeFw0y +NTAxMjEwMzAyNDFaFw0yNzAxMjEwMzAyNDFaMDcxGjAYBgNVBAoTEVRlc3QgT3Jn +YW5pemF0aW9uMRkwFwYDVQQDExB0ZXN0LmV4YW1wbGUuY29tMFwwDQYJKoZIhvcN +AQEBBQADSwAwSAJBAMhnlBxqreifypPjXmyqKZJxTcB5zIMC+OyNRIJc4/WdEBUB +1wmkyOC1Xvr+zuQ8ZaZXMw6n8iS6vP1jnoQnqhcCAwEAAaNCMEAwDgYDVR0PAQH/ +BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8E +BTADAQH/MA0GCSqGSIb3DQEBCwUAA0EAVouJ/As5AYB2xXLq+JofSHWHxTAzvDUb +X9uwNjylgcpxpQUxMPAbSA5kBm6xZpUf2BJfAU76OEUtGA553HLb+g== +-----END CERTIFICATE----- +` + +var cert = ` +-----BEGIN CERTIFICATE----- +MIIB6DCCAZKgAwIBAgIEX2zomzANBgkqhkiG9w0BAQsFADA3MRowGAYDVQQKExFU +ZXN0IE9yZ2FuaXphdGlvbjEZMBcGA1UEAxMQdGVzdC5leGFtcGxlLmNvbTAeFw0y +NTAxMjEwMzAxMjdaFw0yNzAxMjEwMzAxMjdaMEcxDjAMBgNVBAYTBUNoaW5hMRow +GAYDVQQKExFUZXN0IE9yZ2FuaXphdGlvbjEZMBcGA1UEAxMQdGVzdC5leGFtcGxl +LmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDKDo13pjRkv+Kl86siezAjvJ5G +WoS5+G+8EQN/tEHdVFwSR1HqiOCZssRSUUvc0kcabfzPyP2L+BI4wiuQw9avAgMB +AAGjdjB0MA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYB +BQUHAwEwDgYDVR0OBAcEBQECAwQGMDMGA1UdEQQsMCqCEHRlc3QuZXhhbXBsZS5j +b22HBH8AAAGHECABSGAAACABAAAAAAAAAGgwDQYJKoZIhvcNAQELBQADQQBQl8Xq +pEW8DflR+wXtOXU7Q2KVLUrT4C7yaVwS7eMNsbEJerQxuUol6cTCjrILjtKsUjXT +LzsfMZ9rwrvY+PV+ +-----END CERTIFICATE----- +` + +var csrCert = ` +-----BEGIN CERTIFICATE REQUEST----- +MIHkMIGPAgEAMCoxDTALBgNVBAoTBFRlc3QxGTAXBgNVBAMTEHRlc3QuZXhhbXBs +ZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAxzaL40xmGsagoNuG+ngJyVbh +Geoz6gRkXXBs5XyR8ENl9YybbLburu0ajR/vmh/XETTLG2DSBvows2FO1nl9fwID +AQABoAAwDQYJKoZIhvcNAQELBQADQQDE1jMQnEgNp3vg/Xj4YbXCtPOED3fGhyc0 +JPuxgonqBqrDgFL6n1VnWxe8tz6gB3rCccGbNxdkWGzR9y3JQOFc +-----END CERTIFICATE REQUEST----- +` + +func Test_CreatePKCS12Cert(t *testing.T) { + assertError := cryptobin_test.AssertErrorT(t) + assertEqual := cryptobin_test.AssertEqualT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + + pwd := "123123" + + obj := New(). + FromPrivateKey([]byte(prikey)). + FromCertificate([]byte(cert)). + CreatePKCS12Cert(nil, pwd) + p12 := obj.ToKeyString() + + assertError(obj.Error(), "Test_CreatePKCS12Cert") + assertNotEmpty(p12, "Test_CreatePKCS12Cert") + + // =========== + + parseP12 := New().FromPKCS12Cert([]byte(p12), pwd) + + assertEqual(parseP12.GetPrivateKey(), obj.GetPrivateKey(), "Test_CreatePKCS12Cert") +} + +func Test_CreatePKCS12Cert2(t *testing.T) { + assertError := cryptobin_test.AssertErrorT(t) + assertEqual := cryptobin_test.AssertEqualT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + + ca0 := New().FromCertificate([]byte(ca)) + + pwd := "123123" + + obj := New(). + FromPrivateKey([]byte(prikey)). + FromCertificate([]byte(cert)). + CreatePKCS12Cert([]*x509.Certificate{ + ca0.GetCert().ToX509Certificate(), + }, pwd) + p12 := obj.ToKeyString() + + assertError(obj.Error(), "Test_CreatePKCS12Cert2") + assertNotEmpty(p12, "Test_CreatePKCS12Cert2") + + // =========== + + parseP12 := New().FromPKCS12Cert([]byte(p12), pwd) + + assertError(parseP12.Error(), "Test_CreatePKCS12Cert2-FromPKCS12Cert") + assertEqual(parseP12.GetPrivateKey(), obj.GetPrivateKey(), "Test_CreatePKCS12Cert-FromPKCS12Cert") +} + +var caRoot2 = ` +-----BEGIN CERTIFICATE----- +MIIBpDCCAU6gAwIBAgIEDkDUsTANBgkqhkiG9w0BAQsFADA3MRowGAYDVQQKExFU +ZXN0IE9yZ2FuaXphdGlvbjEZMBcGA1UEAxMQdGVzdC5leGFtcGxlLmNvbTAeFw0y +NTAxMjEwNDU5NDhaFw0yNzAxMjEwNDU5NDhaMDcxGjAYBgNVBAoTEVRlc3QgT3Jn +YW5pemF0aW9uMRkwFwYDVQQDExB0ZXN0LmV4YW1wbGUuY29tMFwwDQYJKoZIhvcN +AQEBBQADSwAwSAJBAL3I4OGdootHGfvDwFpDxpMZvVPlLmuh/7gZWBtbn+bsjJgE +iY7GUEU044n/PFxHTAyPKEWGaUn/YbTcHdWJPTMCAwEAAaNCMEAwDgYDVR0PAQH/ +BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8E +BTADAQH/MA0GCSqGSIb3DQEBCwUAA0EApskWhn6L3CEUDXZIMYt4fwoLLztsQzc3 +5dP4kUkdEkRFzlO2BLqsEGpI+ADc08tPmjv3cstbMr5ktg3z73AgCQ== +-----END CERTIFICATE----- +` + +var ca2 = ` +-----BEGIN CERTIFICATE----- +MIIBqDCCAVKgAwIBAgIEQjmW/DANBgkqhkiG9w0BAQsFADA3MRowGAYDVQQKExFU +ZXN0IE9yZ2FuaXphdGlvbjEZMBcGA1UEAxMQdGVzdC5leGFtcGxlLmNvbTAeFw0y +NTAxMjEwNDU5NDhaFw0yODAxMjEwNDU5NDhaMDsxHDAaBgNVBAoTE1Rlc3QyMiBP +cmdhbml6YXRpb24xGzAZBgNVBAMTEnRlc3QyMi5leGFtcGxlLmNvbTBcMA0GCSqG +SIb3DQEBAQUAA0sAMEgCQQCwj671EqiHW+JWDcZRlSEpNWYn0fn1h377RRsPjPo+ +K3Q4mvF2CITPJczAjuMDNwYKUUkK4BwwTlPDKr/ChzADAgMBAAGjQjBAMA4GA1Ud +DwEB/wQEAwIChDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAANBAFRzCc1dHVSOxnM2zA5Fjo0YceL1 +xsRA9/ZP/g6wrVkQVhWf1g6CzDMk07F5yRujdPMKLYVIC/Rt2hCP/F8XZS8= +-----END CERTIFICATE----- +` + +func Test_Verify(t *testing.T) { + assertEqual := cryptobin_test.AssertEqualT(t) + assertError := cryptobin_test.AssertErrorT(t) + + ok, err := New().Verify(caRoot2, ca2, VerifyOptions{ + Intermediates: cryptobin_x509.NewCertPool(), + }) + + assertError(err, "Test_Verify") + assertEqual(ok, true, "Test_Verify") +} + +func Test_Get(t *testing.T) { + assertEqual := cryptobin_test.AssertEqualT(t) + + cert := New(). + FromCertificate([]byte(cert)). + GetCert() + + csr := New(). + FromCertificateRequest([]byte(csrCert)). + GetCertRequest() + + privateKey, _ := rsa.GenerateKey(rand.Reader, 2048) + publicKey := &privateKey.PublicKey + + testerr := errors.New("test-error") + opts := Options{ + PublicKeyType: KeyTypeRSA, + ParameterSizes: dsa.L1024N160, + Curve: elliptic.P256(), + Bits: 2048, + } + + newCA2 := CA{ + cert: cert, + certRequest: csr, + privateKey: privateKey, + publicKey: publicKey, + options: opts, + keyData: []byte("test-keyData"), + Errors: []error{testerr}, + } + + assertEqual(newCA2.GetCert(), cert, "Test_Get-GetCert") + assertEqual(newCA2.GetCertRequest(), csr, "Test_Get-GetCertRequest") + + assertEqual(newCA2.GetPrivateKey(), privateKey, "Test_Get-GetPrivateKey") + assertEqual(newCA2.GetPrivateKeyType().String(), "RSA", "Test_Get-GetPrivateKeyType") + + assertEqual(newCA2.GetPublicKey(), publicKey, "Test_Get-GetPublicKey") + assertEqual(newCA2.GetPublicKeyType().String(), "RSA", "Test_Get-GetPublicKeyType") + + assertEqual(newCA2.GetOptions(), opts, "Test_Get-GetOptions") + assertEqual(newCA2.GetParameterSizes(), dsa.L1024N160, "Test_Get-GetParameterSizes") + assertEqual(newCA2.GetCurve(), elliptic.P256(), "Test_Get-GetCurve") + assertEqual(newCA2.GetBits(), 2048, "Test_Get-GetBits") + + assertEqual(newCA2.GetKeyData(), []byte("test-keyData"), "Test_Get-GetKeyData") + assertEqual(newCA2.GetErrors(), []error{testerr}, "Test_Get-GetErrors") + + assertEqual(newCA2.ToKeyBytes(), []byte("test-keyData"), "Test_Get-ToKeyBytes") + assertEqual(newCA2.ToKeyString(), "test-keyData", "Test_Get-ToKeyString") +} + +func Test_With(t *testing.T) { + assertEqual := cryptobin_test.AssertEqualT(t) + + cert := New(). + FromCertificate([]byte(cert)). + GetCert() + + csr := New(). + FromCertificateRequest([]byte(csrCert)). + GetCertRequest() + + privateKey, _ := rsa.GenerateKey(rand.Reader, 2048) + publicKey := &privateKey.PublicKey + + testerr := errors.New("test-error") + opts := Options{ + PublicKeyType: KeyTypeRSA, + ParameterSizes: dsa.L1024N160, + Curve: elliptic.P256(), + Bits: 2048, + } + + var tmp CA + + newCA := CA{} + + tmp = newCA.WithCert(cert) + assertEqual(tmp.cert, cert, "Test_Get-WithCert") + + tmp = newCA.WithCertRequest(csr) + assertEqual(tmp.certRequest, csr, "Test_Get-WithCertRequest") + + tmp = newCA.WithPrivateKey(privateKey) + assertEqual(tmp.privateKey, privateKey, "Test_Get-WithPrivateKey") + + tmp = newCA.WithPublicKey(publicKey) + assertEqual(tmp.publicKey, publicKey, "Test_Get-WithPublicKey") + + tmp = newCA.WithOptions(opts) + assertEqual(tmp.options, opts, "Test_Get-WithOptions") + + tmp = newCA.WithPublicKeyType(KeyTypeRSA) + assertEqual(tmp.options.PublicKeyType, KeyTypeRSA, "Test_Get-WithPublicKeyType") + + tmp = newCA.SetPublicKeyType("ECDSA") + assertEqual(tmp.options.PublicKeyType, KeyTypeECDSA, "Test_Get-SetPublicKeyType") + + tmp = newCA.SetGenerateType("EdDSA") + assertEqual(tmp.options.PublicKeyType, KeyTypeEdDSA, "Test_Get-SetGenerateType") + + tmp = newCA.WithParameterSizes(dsa.L1024N160) + assertEqual(tmp.options.ParameterSizes, dsa.L1024N160, "Test_Get-WithParameterSizes") + + tmp = newCA.SetParameterSizes("L2048N224") + assertEqual(tmp.options.ParameterSizes, dsa.L2048N224, "Test_Get-SetParameterSizes") + + tmp = newCA.WithCurve(elliptic.P384()) + assertEqual(tmp.options.Curve, elliptic.P384(), "Test_Get-WithCurve") + + tmp = newCA.SetCurve("P521") + assertEqual(tmp.options.Curve, elliptic.P521(), "Test_Get-SetCurve") + + tmp = newCA.WithBits(2048) + assertEqual(tmp.options.Bits, 2048, "Test_Get-WithBits") + + tmp = newCA.WithKeyData([]byte("test-keyData")) + assertEqual(tmp.keyData, []byte("test-keyData"), "Test_Get-WithKeyData") + + tmp = newCA.WithErrors([]error{testerr}) + assertEqual(tmp.Errors, []error{testerr}, "Test_Get-WithErrors") +} diff --git a/cryptobin/ca/create.go b/cryptobin/ca/create.go index 93ded56..494f030 100644 --- a/cryptobin/ca/create.go +++ b/cryptobin/ca/create.go @@ -3,6 +3,7 @@ package ca import ( "fmt" "errors" + "crypto" "crypto/dsa" "crypto/rsa" "crypto/ecdsa" @@ -36,12 +37,22 @@ var ( // Create CA PEM func (this CA) CreateCA() CA { + return this.CreateCAWithIssuer(nil, nil) +} + +// Create CA PEM With Issuer +func (this CA) CreateCAWithIssuer(issuer *cryptobin_x509.Certificate, issuerKey crypto.PrivateKey) CA { if this.publicKey == nil || this.privateKey == nil { err := errors.New("publicKey or privateKey error.") return this.AppendError(err) } - caBytes, err := cryptobin_x509.CreateCertificate(rand.Reader, this.cert, this.cert, this.publicKey, this.privateKey) + if issuer == nil { + issuer = this.cert + issuerKey = this.privateKey + } + + caBytes, err := cryptobin_x509.CreateCertificate(rand.Reader, this.cert, issuer, this.publicKey, issuerKey) if err != nil { return this.AppendError(err) @@ -58,13 +69,13 @@ func (this CA) CreateCA() CA { } // Create Cert PEM -func (this CA) CreateCert(ca *cryptobin_x509.Certificate) CA { +func (this CA) CreateCert(issuer *cryptobin_x509.Certificate, issuerKey crypto.PrivateKey) CA { if this.publicKey == nil || this.privateKey == nil { err := errors.New("publicKey or privateKey error.") return this.AppendError(err) } - certBytes, err := cryptobin_x509.CreateCertificate(rand.Reader, this.cert, ca, this.publicKey, this.privateKey) + certBytes, err := cryptobin_x509.CreateCertificate(rand.Reader, this.cert, issuer, this.publicKey, issuerKey) if err != nil { return this.AppendError(err) } @@ -230,17 +241,15 @@ func (this CA) CreatePublicKey() CA { return this } -// ======================= - // Create PKCS12 Cert PEM // caCerts 通常保留为空 -func (this CA) CreatePKCS12Cert(caCerts []*x509.Certificate, pwd string) CA { +func (this CA) CreatePKCS12Cert(caCerts []*x509.Certificate, password string) CA { if this.privateKey == nil { err := errors.New("privateKey error.") return this.AppendError(err) } - pfxData, err := pkcs12.EncodeChain(rand.Reader, this.privateKey, this.cert.ToX509Certificate(), caCerts, pwd) + pfxData, err := pkcs12.EncodeChain(rand.Reader, this.privateKey, this.cert.ToX509Certificate(), caCerts, password) if err != nil { return this.AppendError(err) } @@ -249,16 +258,3 @@ func (this CA) CreatePKCS12Cert(caCerts []*x509.Certificate, pwd string) CA { return this } - -// pkcs12 密钥 -func (this CA) CreatePKCS12CertTrustStore(certs []*x509.Certificate, password string) CA { - pfxData, err := pkcs12.EncodeTrustStore(rand.Reader, certs, password) - if err != nil { - return this.AppendError(err) - } - - this.keyData = pfxData - - return this -} - diff --git a/cryptobin/ca/from.go b/cryptobin/ca/from.go index b5a4f0e..3412e7d 100644 --- a/cryptobin/ca/from.go +++ b/cryptobin/ca/from.go @@ -89,41 +89,43 @@ func GenerateKey(options ...Options) CA { // ========== -// From Certificate -func (this CA) FromCertificate(der []byte) CA { - cert, err := x509.ParseCertificate(der) +// From Certificate PEM +func (this CA) FromCertificate(cert []byte) CA { + newCert, err := this.ParseCertificateFromPEM(cert) if err != nil { return this.AppendError(err) } - this.cert = cert + this.cert = newCert + this.publicKey = newCert.PublicKey return this } -// From Certificate -func FromCertificate(der []byte) CA { - return defaultCA.FromCertificate(der) +// From Certificate PEM +func FromCertificate(cert []byte) CA { + return defaultCA.FromCertificate(cert) } -// From Certificate Request -func (this CA) FromCertificateRequest(asn1Data []byte) CA { - certRequest, err := x509.ParseCertificateRequest(asn1Data) +// From Certificate Request PEM +func (this CA) FromCertificateRequest(cert []byte) CA { + certRequest, err := this.ParseCertificateRequestFromPEM(cert) if err != nil { return this.AppendError(err) } this.certRequest = certRequest + this.publicKey = certRequest.PublicKey return this } -// From Certificate Request -func FromCertificateRequest(asn1Data []byte) CA { - return defaultCA.FromCertificateRequest(asn1Data) +// From Certificate Request PEM +func FromCertificateRequest(cert []byte) CA { + return defaultCA.FromCertificateRequest(cert) } -// From PrivateKey +// From PrivateKey PEM func (this CA) FromPrivateKey(key []byte) CA { privateKey, err := this.ParsePKCS8PrivateKeyFromPEM(key) if err != nil { @@ -135,12 +137,12 @@ func (this CA) FromPrivateKey(key []byte) CA { return this } -// From PrivateKey +// From PrivateKey PEM func FromPrivateKey(key []byte) CA { return defaultCA.FromPrivateKey(key) } -// From PrivateKey With Password +// From PrivateKey PEM With Password func (this CA) FromPrivateKeyWithPassword(key []byte, password []byte) CA { privateKey, err := this.ParsePKCS8PrivateKeyFromPEMWithPassword(key, password) if err != nil { @@ -152,12 +154,12 @@ func (this CA) FromPrivateKeyWithPassword(key []byte, password []byte) CA { return this } -// From PrivateKey With Password +// From PrivateKey PEM With Password func FromPrivateKeyWithPassword(key []byte, password []byte) CA { return defaultCA.FromPrivateKeyWithPassword(key, password) } -// From PublicKey +// From PublicKey PEM func (this CA) FromPublicKey(key []byte) CA { publicKey, err := this.ParsePKCS8PublicKeyFromPEM(key) if err != nil { @@ -169,7 +171,7 @@ func (this CA) FromPublicKey(key []byte) CA { return this } -// From PublicKey +// From PublicKey PEM func FromPublicKey(key []byte) CA { return defaultCA.FromPublicKey(key) } @@ -178,16 +180,16 @@ func FromPublicKey(key []byte) CA { // pkcs12 func (this CA) FromPKCS12Cert(pfxData []byte, password string) CA { - privateKey, cert, err := pkcs12.Decode(pfxData, password) + privateKey, cert, _, err := pkcs12.DecodeChain(pfxData, password) if err != nil { return this.AppendError(err) } - this.privateKey = privateKey - this.cert = &x509.Certificate{} this.cert.FromX509Certificate(cert) + this.privateKey = privateKey + return this } diff --git a/cryptobin/ca/get.go b/cryptobin/ca/get.go index b661749..bf55140 100644 --- a/cryptobin/ca/get.go +++ b/cryptobin/ca/get.go @@ -8,16 +8,17 @@ import ( "crypto/ed25519" "crypto/elliptic" + "github.com/deatil/go-cryptobin/x509" "github.com/deatil/go-cryptobin/gm/sm2" ) // 获取 cert -func (this CA) GetCert() any { +func (this CA) GetCert() *x509.Certificate { return this.cert } // 获取 certRequest -func (this CA) GetCertRequest() any { +func (this CA) GetCertRequest() *x509.CertificateRequest { return this.certRequest } diff --git a/cryptobin/ca/make.go b/cryptobin/ca/make.go index d1a9534..b1b6e7e 100644 --- a/cryptobin/ca/make.go +++ b/cryptobin/ca/make.go @@ -46,7 +46,7 @@ func (this CA) MakeCA( return this } -// 生成自签名证书 +// 生成证书 func (this CA) MakeCert( subject pkix.Name, expire int, @@ -74,6 +74,8 @@ func (this CA) MakeCert( }, KeyUsage: x509.KeyUsageDigitalSignature, + IsCA: false, + // 签名方式 SignatureAlgorithm: signAlg, } @@ -83,45 +85,44 @@ func (this CA) MakeCert( // 生成证书请求 func (this CA) MakeCSR( - country []string, + commonName string, organization []string, - organizationalUnit []string, - locality []string, - province []string, - streetAddress []string, - postalCode []string, - commonName string, + signAlgName string, ) CA { + signAlg := getSignatureAlgorithm(signAlgName) + this.certRequest = &x509.CertificateRequest{ Subject: pkix.Name{ - Country: country, + CommonName: commonName, Organization: organization, - OrganizationalUnit: organizationalUnit, - Locality: locality, - Province: province, - StreetAddress: streetAddress, - PostalCode: postalCode, - CommonName: commonName, + + // Country: country, + // OrganizationalUnit: organizationalUnit, + // Locality: locality, + // Province: province, + // StreetAddress: streetAddress, + // PostalCode: postalCode, // SerialNumber: string, // Names: []pkix.AttributeTypeAndValue{} // ExtraNames: []pkix.AttributeTypeAndValue{} }, + SignatureAlgorithm: signAlg, } return this } // 更新 Cert 数据 -func (this CA) UpdateCert(fn func(*x509.Certificate) *x509.Certificate) CA { - this.cert = fn(this.cert) +func (this CA) UpdateCert(fn func(*x509.Certificate)) CA { + fn(this.cert) return this } // 更新证书请求数据 -func (this CA) UpdateCertRequest(fn func(*x509.CertificateRequest) *x509.CertificateRequest) CA { - this.certRequest = fn(this.certRequest) +func (this CA) UpdateCertRequest(fn func(*x509.CertificateRequest)) CA { + fn(this.certRequest) return this } diff --git a/cryptobin/ca/parse.go b/cryptobin/ca/parse.go index 5a3936d..85163e8 100644 --- a/cryptobin/ca/parse.go +++ b/cryptobin/ca/parse.go @@ -10,6 +10,7 @@ import ( "github.com/deatil/go-cryptobin/pkcs8" "github.com/deatil/go-cryptobin/gm/sm2" + cryptobin_x509 "github.com/deatil/go-cryptobin/x509" pubkey_dsa "github.com/deatil/go-cryptobin/pubkey/dsa" ) @@ -194,3 +195,25 @@ func (this CA) ParsePKCS8PublicKeyFromPEM(key []byte) (crypto.PublicKey, error) return parsedKey, nil } + +// Parse Certificate From PEM +func (this CA) ParseCertificateFromPEM(cert []byte) (*cryptobin_x509.Certificate, error) { + // Parse PEM block + block, _ := pem.Decode(cert) + if block == nil { + return nil, ErrKeyMustBePEMEncoded + } + + return cryptobin_x509.ParseCertificate(block.Bytes) +} + +// Parse Certificate Request From PEM +func (this CA) ParseCertificateRequestFromPEM(cert []byte) (*cryptobin_x509.CertificateRequest, error) { + // Parse PEM block + block, _ := pem.Decode(cert) + if block == nil { + return nil, ErrKeyMustBePEMEncoded + } + + return cryptobin_x509.ParseCertificateRequest(block.Bytes) +} diff --git a/cryptobin/ca/verify.go b/cryptobin/ca/verify.go index bf6997c..f9bc879 100644 --- a/cryptobin/ca/verify.go +++ b/cryptobin/ca/verify.go @@ -10,6 +10,7 @@ import ( // 验证 func (this CA) Verify(rootPEM string, certPEM string, opts x509.VerifyOptions) (bool, error) { roots := x509.NewCertPool() + ok := roots.AppendCertsFromPEM([]byte(rootPEM)) if !ok { return false, errors.New("failed to parse root certificate") diff --git a/cryptobin/ca/with.go b/cryptobin/ca/with.go index e4faa42..770ec75 100644 --- a/cryptobin/ca/with.go +++ b/cryptobin/ca/with.go @@ -50,7 +50,7 @@ func (this CA) WithPublicKeyType(keyType PublicKeyType) CA { return this } -// public key type +// set public key type // params: // [ RSA | DSA | ECDSA | EdDSA | SM2 ] func (this CA) SetPublicKeyType(keyType string) CA {