From 2896b6a5545c089d45004ab561abcbf912b33c08 Mon Sep 17 00:00:00 2001 From: tim <24852530+cleancodeninja@users.noreply.github.com> Date: Thu, 7 Sep 2017 11:34:01 +0200 Subject: [PATCH] WIP CLI, Add signer struct --- sign.go | 162 ++---------------------------------------------------- signer.go | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+), 156 deletions(-) create mode 100644 signer.go diff --git a/sign.go b/sign.go index 5e50cb2..0980cfc 100644 --- a/sign.go +++ b/sign.go @@ -4,22 +4,12 @@ import ( "flag" "log" "os" - "time" - - "crypto/x509" - "encoding/pem" - "errors" - "io/ioutil" "fmt" - "crypto" - "bitbucket.org/digitorus/pdfsign/config" - "bitbucket.org/digitorus/pdfsign/revocation" "bitbucket.org/digitorus/pdfsign/sign" "bitbucket.org/digitorus/pdfsign/verify" - "bitbucket.org/digitorus/pkcs11" ) // usage is a usage function for the flags package. @@ -134,64 +124,18 @@ Description os.Exit(2) } - cert, signer, err := getCertSignerPair(*crtPath, *keyPath) + s, err := newSigner(*crtPath, *keyPath, *crtChainPath) if err != nil { log.Fatal(err) } - certificate_chains, err := getCertificateChains(*crtChainPath, cert) - if err != nil { - log.Fatal(err) - } - - signData.Signer = signer - signData.Certificate = cert - signData.CertificateChains = certificate_chains - if err := signWithConfig(*inputPath, *outputPath, signData); err != nil { + if err := s.sign(*inputPath, *outputPath, signData); err != nil { log.Println(err) } else { log.Println("Signed PDF written to " + *outputPath) } } -func getCertSignerPair(crtPath, keyPath string) (*x509.Certificate, crypto.Signer, error) { - var certificate *x509.Certificate - var signer crypto.Signer - - // Set certificate - certificate_data, err := ioutil.ReadFile(crtPath) - if err != nil { - return certificate, signer, err - log.Fatal(err) - } - certificate_data_block, _ := pem.Decode(certificate_data) - if certificate_data_block == nil { - return certificate, signer, errors.New("failed to parse PEM block containing the certificate") - } - cert, err := x509.ParseCertificate(certificate_data_block.Bytes) - if err != nil { - return certificate, signer, err - } - certificate = cert - - // Set key - key_data, err := ioutil.ReadFile(keyPath) - if err != nil { - return certificate, signer, err - } - key_data_block, _ := pem.Decode(key_data) - if key_data_block == nil { - return certificate, signer, errors.New("failed to parse PEM block containing the private key") - } - pkey, err := x509.ParsePKCS1PrivateKey(key_data_block.Bytes) - if err != nil { - return certificate, signer, err - } - signer = pkey - - return certificate, signer, nil -} - func p11sign() { signCommand := flag.NewFlagSet("sign", flag.ExitOnError) configPath := signCommand.String("config", "", "Path to config file") @@ -204,9 +148,9 @@ func p11sign() { output := signCommand.String("out", "", "Output PDF file") libPath := signCommand.String("lib", "", "Path to PKCS11 library") pass := signCommand.String("pass", "", "PKCS11 password") - crtChain := signCommand.String("chain", "", "Certificate chain") + crtChainPath := signCommand.String("chain", "", "Certificate chain") help := signCommand.Bool("help", false, "Show this help") - + signData := getSignDataFlags(signCommand) signCommand.Parse(os.Args[2:]) usageText := `Usage: pdfsign sign -in input.pdf -out output.pdf -pass pkcs11-password [-chain chain.crt]") @@ -225,108 +169,14 @@ Description os.Exit(2) } - cert, signer, err := getP11CertSignerPair(*libPath, *pass) + s, err := newP11Signer(*libPath, *pass, *crtChainPath) if err != nil { log.Fatal(err) } - certificate_chains, err := getCertificateChains(*crtChain, cert) - if err != nil { - log.Fatal(err) - } - - var data sign.SignData - data.Certificate = cert - data.Signer = signer - data.CertificateChains = certificate_chains - if err := signWithConfig(*input, *output, data); err != nil { + if err := s.sign(*input, *output, signData); err != nil { log.Println(err) } else { log.Println("Signed PDF written to " + *output) } } - -func getP11CertSignerPair(libPath, pass string) (*x509.Certificate, crypto.Signer, error) { - var certificate *x509.Certificate - var signer crypto.Signer - - // pkcs11 key - lib, err := pkcs11.FindLib(libPath) - if err != nil { - return certificate, signer, err - } - - // Load Library - ctx := pkcs11.New(lib) - if ctx == nil { - return certificate, signer, errors.New("Failed to load library") - } - err = ctx.Initialize() - if err != nil { - return certificate, signer, err - } - // login - session, err := pkcs11.CreateSession(ctx, 0, pass, false) - if err != nil { - return certificate, signer, err - } - // select the first certificate - cert, ckaId, err := pkcs11.GetCert(ctx, session, nil) - if err != nil { - return certificate, signer, err - } - certificate = cert - - // private key - pkey, err := pkcs11.InitPrivateKey(ctx, session, ckaId) - if err != nil { - return certificate, signer, err - } - signer = pkey - - return certificate, signer, nil -} - -func getCertificateChains(crtChain string, cert *x509.Certificate) ([][]*x509.Certificate, error) { - certificate_chains := make([][]*x509.Certificate, 0) - if crtChain == "" { - return certificate_chains, nil - } - - chain_data, err := ioutil.ReadFile(crtChain) - if err != nil { - log.Fatal(err) - } - certificate_pool := x509.NewCertPool() - certificate_pool.AppendCertsFromPEM(chain_data) - certificate_chains, err = cert.Verify(x509.VerifyOptions{ - Intermediates: certificate_pool, - CurrentTime: cert.NotBefore, - KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, - }) - - return certificate_chains, err -} - -func signWithConfig(input, output string, d sign.SignData) error { - err := sign.SignFile(input, output, sign.SignData{ - Signature: sign.SignDataSignature{ - Info: sign.SignDataSignatureInfo{ - Name: d.Signature.Info.Name, - Location: d.Signature.Info.Location, - Reason: d.Signature.Info.Reason, - ContactInfo: d.Signature.Info.ContactInfo, - Date: time.Now().Local(), - }, - CertType: d.Signature.CertType, - Approval: d.Signature.Approval, - }, - Signer: d.Signer, - Certificate: d.Certificate, - CertificateChains: d.CertificateChains, - TSA: d.TSA, - RevocationData: revocation.InfoArchival{}, - RevocationFunction: sign.DefaultEmbedRevocationStatusFunction, - }) - return err -} diff --git a/signer.go b/signer.go new file mode 100644 index 0000000..abc75b9 --- /dev/null +++ b/signer.go @@ -0,0 +1,154 @@ +package main + +import ( + "crypto" + "crypto/x509" + "encoding/pem" + "errors" + "io/ioutil" + "log" + "time" + + "bitbucket.org/digitorus/pdfsign/revocation" + "bitbucket.org/digitorus/pdfsign/sign" + "bitbucket.org/digitorus/pkcs11" +) + +type signer struct { + certificate *x509.Certificate + signer crypto.Signer + certificateChains [][]*x509.Certificate +} + +func newSigner(crtPath, keyPath, crtChainPath string) (*signer, error) { + var s signer + + // Set certificate + certificate_data, err := ioutil.ReadFile(crtPath) + if err != nil { + return &s, err + log.Fatal(err) + } + certificate_data_block, _ := pem.Decode(certificate_data) + if certificate_data_block == nil { + return &s, errors.New("failed to parse PEM block containing the certificate") + } + cert, err := x509.ParseCertificate(certificate_data_block.Bytes) + if err != nil { + return &s, err + } + s.certificate = cert + + // Set key + key_data, err := ioutil.ReadFile(keyPath) + if err != nil { + return &s, err + } + key_data_block, _ := pem.Decode(key_data) + if key_data_block == nil { + return &s, errors.New("failed to parse PEM block containing the private key") + } + pkey, err := x509.ParsePKCS1PrivateKey(key_data_block.Bytes) + if err != nil { + return &s, err + } + s.signer = pkey + + certificate_chains, err := getCertificateChains(crtChainPath, cert) + if err != nil { + return &s, err + } + s.certificateChains = certificate_chains + + return &s, nil +} + +func newP11Signer(libPath, pass, crtChainPath string) (*signer, error) { + var s signer + + // pkcs11 key + lib, err := pkcs11.FindLib(libPath) + if err != nil { + return &s, err + } + + // Load Library + ctx := pkcs11.New(lib) + if ctx == nil { + return &s, errors.New("Failed to load library") + } + err = ctx.Initialize() + if err != nil { + return &s, err + } + // login + session, err := pkcs11.CreateSession(ctx, 0, pass, false) + if err != nil { + return &s, err + } + // select the first certificate + cert, ckaId, err := pkcs11.GetCert(ctx, session, nil) + if err != nil { + return &s, err + } + s.certificate = cert + + // private key + pkey, err := pkcs11.InitPrivateKey(ctx, session, ckaId) + if err != nil { + return &s, err + } + s.signer = pkey + + certificate_chains, err := getCertificateChains(crtChainPath, cert) + if err != nil { + return &s, err + } + s.certificateChains = certificate_chains + + return &s, nil +} + +func getCertificateChains(crtChainPath string, cert *x509.Certificate) ([][]*x509.Certificate, error) { + certificate_chains := make([][]*x509.Certificate, 0) + if crtChainPath == "" { + return certificate_chains, nil + } + + chain_data, err := ioutil.ReadFile(crtChainPath) + if err != nil { + log.Fatal(err) + } + certificate_pool := x509.NewCertPool() + certificate_pool.AppendCertsFromPEM(chain_data) + certificate_chains, err = cert.Verify(x509.VerifyOptions{ + Intermediates: certificate_pool, + CurrentTime: cert.NotBefore, + KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, + }) + + return certificate_chains, err +} + +func (s *signer) sign(input, output string, d sign.SignData) error { + err := sign.SignFile(input, output, sign.SignData{ + Signature: sign.SignDataSignature{ + Info: sign.SignDataSignatureInfo{ + Name: d.Signature.Info.Name, + Location: d.Signature.Info.Location, + Reason: d.Signature.Info.Reason, + ContactInfo: d.Signature.Info.ContactInfo, + Date: time.Now().Local(), + }, + CertType: d.Signature.CertType, + Approval: d.Signature.Approval, + }, + Signer: s.signer, + Certificate: s.certificate, + CertificateChains: s.certificateChains, + TSA: d.TSA, + RevocationData: revocation.InfoArchival{}, + RevocationFunction: sign.DefaultEmbedRevocationStatusFunction, + }) + return err +}