Revert "WIP CLI"

This reverts commit 02b6ee7146.
This commit is contained in:
Jeroen Bobbeldijk
2017-09-17 10:48:09 +02:00
parent 9b09dfada8
commit 411accf30f
3 changed files with 158 additions and 197 deletions

View File

@@ -4,10 +4,14 @@ import (
"log" "log"
"os" "os"
"bitbucket.org/digitorus/pdfsign/sign"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
"github.com/asaskevich/govalidator"
) )
func init() {
govalidator.SetFieldsRequiredByDefault(true)
}
var ( var (
DefaultLocation string = "./pdfsign.conf" // Default location of the config file DefaultLocation string = "./pdfsign.conf" // Default location of the config file
Settings Config // Initialized once inside Read method Settings are stored in memory. Settings Config // Initialized once inside Read method Settings are stored in memory.
@@ -15,8 +19,24 @@ var (
// Config is the root of the config // Config is the root of the config
type Config struct { type Config struct {
Info sign.SignDataSignatureInfo //Info:
TSA sign.TSA //Name: "Jeroen Bobbeldijk",
//Location: "Rotterdam",
//Reason: "Test",
//ContactInfo: "Geen",
//CertType: 2,
//Approval: false,
//TSA: sign.TSA{
//URL: "http://aatl-timestamp.globalsign.com/tsa/aohfewat2389535fnasgnlg5m23",
}
// ValidateFields validates all the fields of the config
func (c Config) ValidateFields() error {
_, err := govalidator.ValidateStruct(c)
if err != nil {
return err
}
return nil
} }
func Read(configfile string) { func Read(configfile string) {
@@ -30,5 +50,9 @@ func Read(configfile string) {
if _, err := toml.DecodeFile(configfile, &c); err != nil { if _, err := toml.DecodeFile(configfile, &c); err != nil {
} }
if err := c.ValidateFields(); err != nil {
log.Fatal("Config is not valid: ", err)
}
Settings = c Settings = c
} }

View File

@@ -20,5 +20,18 @@ staticPath = "../static"
} }
// Root // Root
assert.Equal(t, "../static", c) assert.Equal(t, "../static", c.StaticPath)
}
func TestValidation(t *testing.T) {
const configContent = ``
var c config.Config
if _, err := toml.Decode(configContent, &c); err != nil {
t.Error(err)
}
err := c.ValidateFields()
assert.NotNil(t, err)
} }

310
sign.go
View File

@@ -13,13 +13,9 @@ import (
"fmt" "fmt"
"crypto"
"bitbucket.org/digitorus/pdfsign/config"
"bitbucket.org/digitorus/pdfsign/revocation" "bitbucket.org/digitorus/pdfsign/revocation"
"bitbucket.org/digitorus/pdfsign/sign" "bitbucket.org/digitorus/pdfsign/sign"
"bitbucket.org/digitorus/pdfsign/verify" "bitbucket.org/digitorus/pdfsign/verify"
"bitbucket.org/digitorus/pkcs11"
) )
// usage is a usage function for the flags package. // usage is a usage function for the flags package.
@@ -74,144 +70,18 @@ func verifyPDF() {
} }
} }
func getSignDataFlags(f *flag.FlagSet) sign.SignData {
// Signature info
name := f.String("info-name", config.Settings.Info.Name, "Signature info name")
location := f.String("info-location", config.Settings.Info.Location, "Signature info location")
reason := f.String("info-reason", config.Settings.Info.Reason, "Signature info reason")
contact := f.String("info-contact", config.Settings.Info.ContactInfo, "Signature info contact")
// Signature other
approval := f.Bool("approval", false, "Approval")
certType := f.Uint("type", 0, "Certificate type")
// TSA
tsaUrl := f.String("tsa-url", "", "tsaUrl")
tsaUsername := f.String("tsa-username", "", "tsaUsername")
tsaPassword := f.String("tsa-password", "", "tsaPassword")
var sd sign.SignData
sd.Signature.Info.Name = *name
sd.Signature.Info.Location = *location
sd.Signature.Info.Reason = *reason
sd.Signature.Info.ContactInfo = *contact
sd.Signature.CertType = uint32(*certType)
sd.Signature.Approval = *approval
sd.TSA.URL = *tsaUrl
sd.TSA.Username = *tsaUsername
sd.TSA.Password = *tsaPassword
return sd
}
func simpleSign() { func simpleSign() {
signCommand := flag.NewFlagSet("sign", flag.ExitOnError) signCommand := flag.NewFlagSet("sign", flag.ExitOnError)
configPath := signCommand.String("config", "", "Path to config file")
signCommand.Parse(os.Args[2:])
if *configPath != "" {
config.Read(*configPath)
}
inputPath := signCommand.String("in", "", "Input PDF file")
outputPath := signCommand.String("out", "", "Output PDF file")
crtPath := signCommand.String("crt", "", "Certificate")
keyPath := signCommand.String("key", "", "Private key")
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 -crt certificate.crt -key private_key.key [-chain chain.crt]")
Description
`
if *help == true {
fmt.Println(usageText)
signCommand.PrintDefaults()
return
}
if signCommand.Parsed() == false || *inputPath == "" || *outputPath == "" || *crtPath == "" || *keyPath == "" {
fmt.Println(usageText)
signCommand.PrintDefaults()
os.Exit(2)
}
cert, signer, err := getCertSignerPair(*crtPath, *keyPath)
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 {
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")
signCommand.Parse(os.Args[2:])
if *configPath != "" {
config.Read(*configPath)
}
input := signCommand.String("in", "", "Input PDF file") input := signCommand.String("in", "", "Input PDF file")
output := signCommand.String("out", "", "Output PDF file") output := signCommand.String("out", "", "Output PDF file")
libPath := signCommand.String("lib", "", "Path to PKCS11 library") crt := signCommand.String("crt", "", "Certificate")
pass := signCommand.String("pass", "", "PKCS11 password") key := signCommand.String("key", "", "Private key")
crtChain := signCommand.String("chain", "", "Certificate chain") crtChain := signCommand.String("chain", "", "Certificate chain")
help := signCommand.Bool("help", false, "Show this help") help := signCommand.Bool("help", false, "Show this help")
signCommand.Parse(os.Args[2:]) signCommand.Parse(os.Args[2:])
usageText := `Usage: pdfsign sign -in input.pdf -out output.pdf -pass pkcs11-password [-chain chain.crt]") usageText := `usageText: pdfsign sign -in input.pdf -out output.pdf -crt certificate.crt -key private_key.key [-chain chain.crt]\n\n")
Description Description
` `
if *help == true { if *help == true {
fmt.Println(usageText) fmt.Println(usageText)
@@ -219,13 +89,34 @@ Description
return return
} }
if signCommand.Parsed() == false || *input == "" || *output == "" || *pass == "" { if signCommand.Parsed() == false || *input == "" || *output == "" || *crt == "" || *key == "" {
fmt.Println(usageText) fmt.Println(usageText)
signCommand.PrintDefaults() signCommand.PrintDefaults()
os.Exit(2) os.Exit(1)
} }
cert, signer, err := getP11CertSignerPair(*libPath, *pass) certificate_data, err := ioutil.ReadFile(*crt)
if err != nil {
log.Fatal(err)
}
certificate_data_block, _ := pem.Decode(certificate_data)
if certificate_data_block == nil {
log.Fatal(errors.New("failed to parse PEM block containing the certificate"))
}
cert, err := x509.ParseCertificate(certificate_data_block.Bytes)
if err != nil {
log.Fatal(err)
}
key_data, err := ioutil.ReadFile(*key)
if err != nil {
log.Fatal(err)
}
key_data_block, _ := pem.Decode(key_data)
if key_data_block == nil {
log.Fatal(errors.New("failed to parse PEM block containing the private key"))
}
pkey, err := x509.ParsePKCS1PrivateKey(key_data_block.Bytes)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@@ -236,55 +127,82 @@ Description
} }
var data sign.SignData var data sign.SignData
data.Signer = pkey
data.Certificate = cert data.Certificate = cert
data.Signer = signer
data.CertificateChains = certificate_chains data.CertificateChains = certificate_chains
if err := signWithConfig(*input, *output, data); err != nil { signWithConfig(*input, *output, data)
log.Println(err)
} else {
log.Println("Signed PDF written to " + *output)
}
} }
func getP11CertSignerPair(libPath, pass string) (*x509.Certificate, crypto.Signer, error) { func p11sign() {
var certificate *x509.Certificate //if len(flag.Args()) < 2 {
var signer crypto.Signer // usage()
//}
// pkcs11 key //
lib, err := pkcs11.FindLib(libPath) //method := flag.Arg(0)
if err != nil { //if method != "sign" && method != "verify" {
return certificate, signer, err // usage()
} //}
//
// Load Library //input := flag.Arg(1)
ctx := pkcs11.New(lib) //if len(input) == 0 {
if ctx == nil { // usage()
return certificate, signer, errors.New("Failed to load library") //}
} //
err = ctx.Initialize() //if method == "verify" {
if err != nil { // input_file, err := os.Open(input)
return certificate, signer, err // if err != nil {
} // log.Fatal(err)
// login // }
session, err := pkcs11.CreateSession(ctx, 0, pass, false) // defer input_file.Close()
if err != nil { //
return certificate, signer, err // resp, err := verify.Verify(input_file)
} // log.Println(resp)
// select the first certificate // if err != nil {
cert, ckaId, err := pkcs11.GetCert(ctx, session, nil) // log.Println(err)
if err != nil { // }
return certificate, signer, err //}
} //
certificate = cert //if method == "sign" {
// if len(flag.Args()) < 4 {
// private key // usage()
pkey, err := pkcs11.InitPrivateKey(ctx, session, ckaId) // }
if err != nil { //
return certificate, signer, err // output := flag.Arg(2)
} // if len(output) == 0 {
signer = pkey // usage()
// }
return certificate, signer, nil //
// // pkcs11 key
// lib, err := pkcs11.FindLib("/lib64/libeTPkcs11.so")
// if err != nil {
// log.Fatal(err)
// }
//
// // Load Library
// ctx := pkcs11.New(lib)
// if ctx == nil {
// log.Fatal("Failed to load library")
// }
// err = ctx.Initialize()
// if err != nil {
// log.Fatal(err)
// }
// // login
// session, err := pkcs11.CreateSession(ctx, 0, flag.Arg(3), false)
// if err != nil {
// log.Fatal(err)
// }
// // select the first certificate
// cert, ckaId, err := pkcs11.GetCert(ctx, session, nil)
// if err != nil {
// log.Fatal(err)
// }
//
// // private key
// pkey, err := pkcs11.InitPrivateKey(ctx, session, ckaId)
// if err != nil {
// log.Fatal(err)
// }
} }
func getCertificateChains(crtChain string, cert *x509.Certificate) ([][]*x509.Certificate, error) { func getCertificateChains(crtChain string, cert *x509.Certificate) ([][]*x509.Certificate, error) {
@@ -308,25 +226,31 @@ func getCertificateChains(crtChain string, cert *x509.Certificate) ([][]*x509.Ce
return certificate_chains, err return certificate_chains, err
} }
func signWithConfig(input, output string, d sign.SignData) error { func signWithConfig(input, output string, data sign.SignData) {
err := sign.SignFile(input, output, sign.SignData{ err := sign.SignFile(input, output, sign.SignData{
Signature: sign.SignDataSignature{ Signature: sign.SignDataSignature{
Info: sign.SignDataSignatureInfo{ Info: sign.SignDataSignatureInfo{
Name: d.Signature.Info.Name, Name: "Jeroen Bobbeldijk",
Location: d.Signature.Info.Location, Location: "Rotterdam",
Reason: d.Signature.Info.Reason, Reason: "Test",
ContactInfo: d.Signature.Info.ContactInfo, ContactInfo: "Geen",
Date: time.Now().Local(), Date: time.Now().Local(),
}, },
CertType: d.Signature.CertType, CertType: 2,
Approval: d.Signature.Approval, Approval: false,
},
Signer: data.Signer,
Certificate: data.Certificate,
CertificateChains: data.CertificateChains,
TSA: sign.TSA{
URL: "http://aatl-timestamp.globalsign.com/tsa/aohfewat2389535fnasgnlg5m23",
}, },
Signer: d.Signer,
Certificate: d.Certificate,
CertificateChains: d.CertificateChains,
TSA: d.TSA,
RevocationData: revocation.InfoArchival{}, RevocationData: revocation.InfoArchival{},
RevocationFunction: sign.DefaultEmbedRevocationStatusFunction, RevocationFunction: sign.DefaultEmbedRevocationStatusFunction,
}) })
return err if err != nil {
log.Println(err)
} else {
log.Println("Signed PDF written to " + output)
}
} }