@@ -321,8 +321,9 @@ type CertChain struct {
321
321
CertPEM , CACertPEM []byte
322
322
PrivKeyPEM , CAPrivKeyPEM []byte
323
323
324
- CACert * x509.Certificate
325
- CAPrivKey * rsa.PrivateKey
324
+ CACert * x509.Certificate
325
+ CAPrivKey * rsa.PrivateKey
326
+ CAPrivKeyECDSA * ecdsa.PrivateKey
326
327
}
327
328
328
329
func (cc * CertChain ) AsTLSConfig () * tls.Config {
@@ -397,6 +398,50 @@ func CreateExpiredSignedCertWithRootCA(cert CertNames) CertChain {
397
398
}
398
399
}
399
400
401
+ func CreateSignedECDSACertWithRootCA (cert CertNames ) CertChain {
402
+ rootPrivateKey , rootCADER := CreateECDSACertDER ("theCA" )
403
+ // generate a random serial number (a real cert authority would have some logic behind this)
404
+ serialNumberLimit := new (big.Int ).Lsh (big .NewInt (1 ), 128 )
405
+ serialNumber , err := rand .Int (rand .Reader , serialNumberLimit )
406
+ Expect (err ).ToNot (HaveOccurred ())
407
+
408
+ subject := pkix.Name {Organization : []string {"xyz, Inc." }}
409
+
410
+ certTemplate := x509.Certificate {
411
+ SerialNumber : serialNumber ,
412
+ Subject : subject ,
413
+ SignatureAlgorithm : x509 .ECDSAWithSHA256 ,
414
+ NotBefore : time .Now (),
415
+ NotAfter : time .Now ().Add (time .Hour ), // valid for an hour
416
+ BasicConstraintsValid : true ,
417
+ }
418
+ if cert .SANs .IP != "" {
419
+ certTemplate .IPAddresses = []net.IP {net .ParseIP (cert .SANs .IP )}
420
+ }
421
+
422
+ if cert .SANs .DNS != "" {
423
+ certTemplate .DNSNames = []string {cert .SANs .DNS }
424
+ }
425
+ rootCert , err := x509 .ParseCertificate (rootCADER )
426
+ Expect (err ).NotTo (HaveOccurred ())
427
+
428
+ ownKey , err := ecdsa .GenerateKey (elliptic .P256 (), rand .Reader )
429
+ Expect (err ).NotTo (HaveOccurred ())
430
+
431
+ certDER , err := x509 .CreateCertificate (rand .Reader , & certTemplate , rootCert , & ownKey .PublicKey , rootPrivateKey )
432
+ Expect (err ).NotTo (HaveOccurred ())
433
+ ownKeyPEM , ownCertPEM := CreateECDSAKeyPairFromDER (certDER , ownKey )
434
+ rootKeyPEM , rootCertPEM := CreateECDSAKeyPairFromDER (rootCADER , rootPrivateKey )
435
+ return CertChain {
436
+ CertPEM : ownCertPEM ,
437
+ PrivKeyPEM : ownKeyPEM ,
438
+ CACertPEM : rootCertPEM ,
439
+ CAPrivKeyPEM : rootKeyPEM ,
440
+ CACert : rootCert ,
441
+ CAPrivKeyECDSA : rootPrivateKey ,
442
+ }
443
+ }
444
+
400
445
func CreateSignedCertWithRootCA (cert CertNames ) CertChain {
401
446
rootPrivateKey , rootCADER := CreateCertDER ("theCA" )
402
447
// generate a random serial number (a real cert authority would have some logic behind this)
@@ -446,6 +491,37 @@ func (c *CertChain) TLSCert() tls.Certificate {
446
491
return cert
447
492
}
448
493
494
+ func CreateECDSACertDER (cname string ) (* ecdsa.PrivateKey , []byte ) {
495
+ // generate a random serial number (a real cert authority would have some logic behind this)
496
+ serialNumberLimit := new (big.Int ).Lsh (big .NewInt (1 ), 128 )
497
+ serialNumber , err := rand .Int (rand .Reader , serialNumberLimit )
498
+ Expect (err ).ToNot (HaveOccurred ())
499
+
500
+ subject := pkix.Name {Organization : []string {"xyz, Inc." }}
501
+ if cname != "" {
502
+ subject .CommonName = cname
503
+ }
504
+
505
+ tmpl := x509.Certificate {
506
+ SerialNumber : serialNumber ,
507
+ Subject : subject ,
508
+ SignatureAlgorithm : x509 .ECDSAWithSHA256 ,
509
+ NotBefore : time .Now (),
510
+ NotAfter : time .Now ().Add (time .Hour ), // valid for an hour
511
+ BasicConstraintsValid : true ,
512
+ IPAddresses : []net.IP {net .ParseIP ("127.0.0.1" )},
513
+ DNSNames : []string {cname },
514
+ KeyUsage : x509 .KeyUsageCertSign | x509 .KeyUsageDigitalSignature ,
515
+ ExtKeyUsage : []x509.ExtKeyUsage {x509 .ExtKeyUsageServerAuth , x509 .ExtKeyUsageClientAuth },
516
+ IsCA : true ,
517
+ }
518
+
519
+ privKey , err := ecdsa .GenerateKey (elliptic .P256 (), rand .Reader )
520
+ Expect (err ).ToNot (HaveOccurred ())
521
+ certDER , err := x509 .CreateCertificate (rand .Reader , & tmpl , & tmpl , & privKey .PublicKey , privKey )
522
+ Expect (err ).ToNot (HaveOccurred ())
523
+ return privKey , certDER
524
+ }
449
525
func CreateCertDER (cname string ) (* rsa.PrivateKey , []byte ) {
450
526
// generate a random serial number (a real cert authority would have some logic behind this)
451
527
serialNumberLimit := new (big.Int ).Lsh (big .NewInt (1 ), 128 )
@@ -478,6 +554,18 @@ func CreateCertDER(cname string) (*rsa.PrivateKey, []byte) {
478
554
return privKey , certDER
479
555
}
480
556
557
+ func CreateECDSAKeyPairFromDER (certDER []byte , privKey * ecdsa.PrivateKey ) (keyPEM , certPEM []byte ) {
558
+ b := pem.Block {Type : "CERTIFICATE" , Bytes : certDER }
559
+ certPEM = pem .EncodeToMemory (& b )
560
+ keyB , err := x509 .MarshalECPrivateKey (privKey )
561
+ Expect (err ).ToNot (HaveOccurred ())
562
+ keyPEM = pem .EncodeToMemory (& pem.Block {
563
+ Type : "RSA PRIVATE KEY" ,
564
+ Bytes : keyB ,
565
+ })
566
+
567
+ return
568
+ }
481
569
func CreateKeyPairFromDER (certDER []byte , privKey * rsa.PrivateKey ) (keyPEM , certPEM []byte ) {
482
570
b := pem.Block {Type : "CERTIFICATE" , Bytes : certDER }
483
571
certPEM = pem .EncodeToMemory (& b )
0 commit comments