Revert "WIP - Command line tool"

This reverts commit b478d6efe8.
This commit is contained in:
Jeroen Bobbeldijk
2017-09-17 10:48:24 +02:00
parent 515058212d
commit 322998775c
6 changed files with 105 additions and 315 deletions

3
.gitignore vendored
View File

@@ -1,3 +0,0 @@
pdfsign
certs/
.realize/

View File

@@ -1,58 +0,0 @@
package config
import (
"log"
"os"
"github.com/BurntSushi/toml"
"github.com/asaskevich/govalidator"
)
func init() {
govalidator.SetFieldsRequiredByDefault(true)
}
var (
DefaultLocation string = "./pdfsign.conf" // Default location of the config file
Settings Config // Initialized once inside Read method Settings are stored in memory.
)
// Config is the root of the config
type Config struct {
//Info:
//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) {
_, err := os.Stat(configfile)
if err != nil {
log.Fatal("Config file is missing: ", configfile)
}
var c Config
if _, err := toml.DecodeFile(configfile, &c); err != nil {
}
if err := c.ValidateFields(); err != nil {
log.Fatal("Config is not valid: ", err)
}
Settings = c
}

View File

@@ -1,37 +0,0 @@
package config_test
import (
"testing"
"bitbucket.org/digitorus/littlewatcher/src/config"
"github.com/BurntSushi/toml"
"github.com/stretchr/testify/assert"
)
func TestConfig(t *testing.T) {
const configContent = `
staticPath = "../static"
`
var c config.Config
if _, err := toml.Decode(configContent, &c); err != nil {
t.Error(err)
}
// Root
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)
}

318
sign.go
View File

@@ -11,246 +11,134 @@ import (
"errors" "errors"
"io/ioutil" "io/ioutil"
"fmt"
"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"
) )
// usage is a usage function for the flags package.
func usage() { func usage() {
fmt.Fprintf(os.Stderr, "Pdfsign is a tool to sign and verifyPDF PDF digital signatures\n\n") log.Fatal("Usage: sign input.pdf output.pdf certificate.crt private_key.key [chain.crt] OR verify input.pdf")
fmt.Fprintf(os.Stderr, "Usage:\n\n")
fmt.Fprintf(os.Stderr, "\tpdfsign command [arguments]\n\n")
fmt.Fprintf(os.Stderr, "The commands are:\n\n")
fmt.Fprintf(os.Stderr, "\tsign \t\tsign single PDF document\n")
fmt.Fprintf(os.Stderr, "\tverifyPDF \t\tverifyPDF signature of single PDF document\n")
fmt.Fprintf(os.Stderr, "\tserve \t\tserve web API with signing capabilities. API documentation url\n")
fmt.Fprintf(os.Stderr, "\twatch \t\tautomatically sign PDF files inside a folder\n")
fmt.Fprintf(os.Stderr, "\n\n")
flag.PrintDefaults()
os.Exit(2)
} }
func main() { func main() {
// if no flags provided print usage flag.Parse()
if len(os.Args) == 1 {
if len(flag.Args()) < 2 {
usage() usage()
return
} }
switch os.Args[1] { method := flag.Arg(0)
case "sign": if method != "sign" && method != "verify" {
simpleSign() usage()
case "verifyPDF":
verifyPDF()
case "serve":
case "watch":
default:
fmt.Printf("%q is not valid command.\n", os.Args[1])
os.Exit(2)
}
}
func verifyPDF() {
verifyCommand := flag.NewFlagSet("verifyPDF", flag.ExitOnError)
input := verifyCommand.String("in", "", "")
input_file, err := os.Open(*input)
if err != nil {
log.Fatal(err)
}
defer input_file.Close()
resp, err := verify.Verify(input_file)
log.Println(resp)
if err != nil {
log.Println(err)
}
}
func simpleSign() {
signCommand := flag.NewFlagSet("sign", flag.ExitOnError)
input := signCommand.String("in", "", "Input PDF file")
output := signCommand.String("out", "", "Output PDF file")
crt := signCommand.String("crt", "", "Certificate")
key := signCommand.String("key", "", "Private key")
crtChain := signCommand.String("chain", "", "Certificate chain")
help := signCommand.Bool("help", false, "Show this help")
signCommand.Parse(os.Args[2:])
usageText := `usageText: pdfsign sign -in input.pdf -out output.pdf -crt certificate.crt -key private_key.key [-chain chain.crt]\n\n")
Description
`
if *help == true {
fmt.Println(usageText)
signCommand.PrintDefaults()
return
} }
if signCommand.Parsed() == false || *input == "" || *output == "" || *crt == "" || *key == "" { input := flag.Arg(1)
fmt.Println(usageText) if len(input) == 0 {
signCommand.PrintDefaults() usage()
os.Exit(1)
} }
certificate_data, err := ioutil.ReadFile(*crt) if method == "verify" {
if err != nil { input_file, err := os.Open(input)
log.Fatal(err) if err != nil {
} log.Fatal(err)
certificate_data_block, _ := pem.Decode(certificate_data) }
if certificate_data_block == nil { defer input_file.Close()
log.Fatal(errors.New("failed to parse PEM block containing the certificate"))
} resp, err := verify.Verify(input_file)
cert, err := x509.ParseCertificate(certificate_data_block.Bytes) log.Println(resp)
if err != nil { if err != nil {
log.Fatal(err) log.Println(err)
}
} }
key_data, err := ioutil.ReadFile(*key) if method == "sign" {
if err != nil { if len(flag.Args()) < 5 {
log.Fatal(err) usage()
} }
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 {
log.Fatal(err)
}
certificate_chains, err := getCertificateChains(*crtChain, cert) output := flag.Arg(2)
if err != nil { if len(output) == 0 {
log.Fatal(err) usage()
} }
var data sign.SignData certificate_data, err := ioutil.ReadFile(flag.Arg(3))
data.Signer = pkey if err != nil {
data.Certificate = cert log.Fatal(err)
data.CertificateChains = certificate_chains
signWithConfig(*input, *output, data)
}
func p11sign() { }
//if len(flag.Args()) < 2 { certificate_data_block, _ := pem.Decode(certificate_data)
// usage() if certificate_data_block == nil {
//} log.Fatal(errors.New("failed to parse PEM block containing the certificate"))
// }
//method := flag.Arg(0)
//if method != "sign" && method != "verifyPDF" {
// usage()
//}
//
//input := flag.Arg(1)
//if len(input) == 0 {
// usage()
//}
//
//if method == "verifyPDF" {
// input_file, err := os.Open(input)
// if err != nil {
// log.Fatal(err)
// }
// defer input_file.Close()
//
// resp, err := verify.Verify(input_file)
// log.Println(resp)
// if err != nil {
// log.Println(err)
// }
//}
//
//if method == "sign" {
// if len(flag.Args()) < 4 {
// usage()
// }
//
// output := flag.Arg(2)
// if len(output) == 0 {
// usage()
// }
//
// // 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) { cert, err := x509.ParseCertificate(certificate_data_block.Bytes)
certificate_chains := make([][]*x509.Certificate, 0) if err != nil {
if crtChain == "" { log.Fatal(err)
return certificate_chains, nil }
}
chain_data, err := ioutil.ReadFile(crtChain) key_data, err := ioutil.ReadFile(flag.Arg(4))
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
certificate_pool := x509.NewCertPool() key_data_block, _ := pem.Decode(key_data)
certificate_pool.AppendCertsFromPEM(chain_data) if key_data_block == nil {
certificate_chains, err = cert.Verify(x509.VerifyOptions{ log.Fatal(errors.New("failed to parse PEM block containing the private key"))
Intermediates: certificate_pool, }
CurrentTime: cert.NotBefore,
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
})
return certificate_chains, err pkey, err := x509.ParsePKCS1PrivateKey(key_data_block.Bytes)
} if err != nil {
log.Fatal(err)
}
func signWithConfig(input, output string, data sign.SignData) { certificate_chains := make([][]*x509.Certificate, 0)
err := sign.SignFile(input, output, sign.SignData{
Signature: sign.SignDataSignature{ if flag.Arg(5) != "" {
Info: sign.SignDataSignatureInfo{ certificate_pool := x509.NewCertPool()
Name: "Jeroen Bobbeldijk", if err != nil {
Location: "Rotterdam", log.Fatal(err)
Reason: "Test", }
ContactInfo: "Geen",
Date: time.Now().Local(), chain_data, err := ioutil.ReadFile(flag.Arg(5))
if err != nil {
log.Fatal(err)
}
certificate_pool.AppendCertsFromPEM(chain_data)
certificate_chains, err = cert.Verify(x509.VerifyOptions{
Intermediates: certificate_pool,
CurrentTime: cert.NotBefore,
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
})
if err != nil {
log.Fatal(err)
}
}
err = sign.SignFile(input, output, sign.SignData{
Signature: sign.SignDataSignature{
Info: sign.SignDataSignatureInfo{
Name: "Jeroen Bobbeldijk",
Location: "Rotterdam",
Reason: "Test",
ContactInfo: "Geen",
Date: time.Now().Local(),
},
CertType: 2,
Approval: false,
}, },
CertType: 2, Signer: pkey,
Approval: false, Certificate: cert,
}, CertificateChains: certificate_chains,
Signer: data.Signer, TSA: sign.TSA{
Certificate: data.Certificate, URL: "http://aatl-timestamp.globalsign.com/tsa/aohfewat2389535fnasgnlg5m23",
CertificateChains: data.CertificateChains, },
TSA: sign.TSA{ RevocationData: revocation.InfoArchival{},
URL: "http://aatl-timestamp.globalsign.com/tsa/aohfewat2389535fnasgnlg5m23", RevocationFunction: sign.DefaultEmbedRevocationStatusFunction,
}, })
RevocationData: revocation.InfoArchival{}, if err != nil {
RevocationFunction: sign.DefaultEmbedRevocationStatusFunction, log.Println(err)
}) } else {
if err != nil { log.Println("Signed PDF written to " + output)
log.Println(err) }
} else {
log.Println("Signed PDF written to " + output)
} }
} }

View File

@@ -12,11 +12,11 @@ import (
"bitbucket.org/digitorus/pdf" "bitbucket.org/digitorus/pdf"
"bitbucket.org/digitorus/pdfsign/revocation" "bitbucket.org/digitorus/pdfsign/revocation"
"crypto"
"github.com/digitorus/pkcs7" "github.com/digitorus/pkcs7"
"github.com/digitorus/timestamp" "github.com/digitorus/timestamp"
"golang.org/x/crypto/ocsp"
"log" "log"
"golang.org/x/crypto/ocsp"
"crypto"
) )
type Response struct { type Response struct {