diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 23abe13..0000000 --- a/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -pdfsign -certs/ -.realize/ \ No newline at end of file diff --git a/config/config.go b/config/config.go deleted file mode 100644 index 3728493..0000000 --- a/config/config.go +++ /dev/null @@ -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 -} diff --git a/config/config_test.go b/config/config_test.go deleted file mode 100644 index ad3e1b7..0000000 --- a/config/config_test.go +++ /dev/null @@ -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) -} diff --git a/p11sign.go_ b/p11sign.go similarity index 100% rename from p11sign.go_ rename to p11sign.go diff --git a/sign.go b/sign.go index d947829..22e8931 100644 --- a/sign.go +++ b/sign.go @@ -11,246 +11,134 @@ import ( "errors" "io/ioutil" - "fmt" - "bitbucket.org/digitorus/pdfsign/revocation" "bitbucket.org/digitorus/pdfsign/sign" "bitbucket.org/digitorus/pdfsign/verify" ) -// usage is a usage function for the flags package. func usage() { - fmt.Fprintf(os.Stderr, "Pdfsign is a tool to sign and verifyPDF PDF digital signatures\n\n") - 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) + log.Fatal("Usage: sign input.pdf output.pdf certificate.crt private_key.key [chain.crt] OR verify input.pdf") } func main() { - // if no flags provided print usage - if len(os.Args) == 1 { + flag.Parse() + + if len(flag.Args()) < 2 { usage() - return } - switch os.Args[1] { - case "sign": - simpleSign() - 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 + method := flag.Arg(0) + if method != "sign" && method != "verify" { + usage() } - if signCommand.Parsed() == false || *input == "" || *output == "" || *crt == "" || *key == "" { - fmt.Println(usageText) - signCommand.PrintDefaults() - os.Exit(1) + input := flag.Arg(1) + if len(input) == 0 { + usage() } - 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) + if method == "verify" { + 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) + } } - 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 { - log.Fatal(err) - } + if method == "sign" { + if len(flag.Args()) < 5 { + usage() + } - certificate_chains, err := getCertificateChains(*crtChain, cert) - if err != nil { - log.Fatal(err) - } + output := flag.Arg(2) + if len(output) == 0 { + usage() + } - var data sign.SignData - data.Signer = pkey - data.Certificate = cert - data.CertificateChains = certificate_chains - signWithConfig(*input, *output, data) -} + certificate_data, err := ioutil.ReadFile(flag.Arg(3)) + if err != nil { + log.Fatal(err) -func p11sign() { - //if len(flag.Args()) < 2 { - // usage() - //} - // - //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) - // } -} + } + certificate_data_block, _ := pem.Decode(certificate_data) + if certificate_data_block == nil { + log.Fatal(errors.New("failed to parse PEM block containing the certificate")) + } -func getCertificateChains(crtChain string, cert *x509.Certificate) ([][]*x509.Certificate, error) { - certificate_chains := make([][]*x509.Certificate, 0) - if crtChain == "" { - return certificate_chains, nil - } + cert, err := x509.ParseCertificate(certificate_data_block.Bytes) + if err != nil { + log.Fatal(err) + } - 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}, - }) + key_data, err := ioutil.ReadFile(flag.Arg(4)) + 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")) + } - 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) { - 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(), + certificate_chains := make([][]*x509.Certificate, 0) + + if flag.Arg(5) != "" { + certificate_pool := x509.NewCertPool() + if err != nil { + log.Fatal(err) + } + + 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, - Approval: false, - }, - Signer: data.Signer, - Certificate: data.Certificate, - CertificateChains: data.CertificateChains, - TSA: sign.TSA{ - URL: "http://aatl-timestamp.globalsign.com/tsa/aohfewat2389535fnasgnlg5m23", - }, - RevocationData: revocation.InfoArchival{}, - RevocationFunction: sign.DefaultEmbedRevocationStatusFunction, - }) - if err != nil { - log.Println(err) - } else { - log.Println("Signed PDF written to " + output) + Signer: pkey, + Certificate: cert, + CertificateChains: certificate_chains, + TSA: sign.TSA{ + URL: "http://aatl-timestamp.globalsign.com/tsa/aohfewat2389535fnasgnlg5m23", + }, + RevocationData: revocation.InfoArchival{}, + RevocationFunction: sign.DefaultEmbedRevocationStatusFunction, + }) + if err != nil { + log.Println(err) + } else { + log.Println("Signed PDF written to " + output) + } } } diff --git a/verify/verify.go b/verify/verify.go index 8e4fd12..06b7e89 100644 --- a/verify/verify.go +++ b/verify/verify.go @@ -12,11 +12,11 @@ import ( "bitbucket.org/digitorus/pdf" "bitbucket.org/digitorus/pdfsign/revocation" - "crypto" "github.com/digitorus/pkcs7" "github.com/digitorus/timestamp" - "golang.org/x/crypto/ocsp" "log" + "golang.org/x/crypto/ocsp" + "crypto" ) type Response struct {