WIP CLI, Add signer struct

This commit is contained in:
tim
2017-09-07 11:34:01 +02:00
parent 02b6ee7146
commit 2896b6a554
2 changed files with 160 additions and 156 deletions

162
sign.go
View File

@@ -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
}

154
signer.go Normal file
View File

@@ -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
}