From a0393425ce710389ed538a463435d822e441516e Mon Sep 17 00:00:00 2001 From: Jeroen Bobbeldijk Date: Wed, 19 Jul 2017 21:33:58 +0200 Subject: [PATCH] Fix TSA --- sign.go | 2 ++ sign/pdfsignature.go | 83 ++++++++++++++++++++------------------------ verify/verify.go | 19 +++++++++- 3 files changed, 57 insertions(+), 47 deletions(-) diff --git a/sign.go b/sign.go index 80f5851..22e8931 100644 --- a/sign.go +++ b/sign.go @@ -106,6 +106,8 @@ func main() { 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) diff --git a/sign/pdfsignature.go b/sign/pdfsignature.go index f710caf..5d94b7b 100644 --- a/sign/pdfsignature.go +++ b/sign/pdfsignature.go @@ -111,52 +111,6 @@ func (context *SignContext) createSignature() ([]byte, error) { TSATokenChain := make([][]*x509.Certificate, 0) - if context.SignData.TSA.URL != "" { - timestamp_response, err := context.GetTSA(sign_content) - if err != nil { - return nil, err - } - - var rest []byte - var resp TSAResponse - if rest, err = asn1.Unmarshal(timestamp_response, &resp); err != nil { - return nil, err - } - if len(rest) > 0 { - return nil, errors.New("trailing data in Time-Stamp response") - } - - if resp.Status.Status > 0 { - return nil, errors.New(fmt.Sprintf("%s: %s", timestamp.FailureInfo(resp.Status.FailInfo).String(), resp.Status.StatusString)) - } - - timestamp_p7, err := pkcs7.Parse(resp.TimeStampToken.FullBytes) - if err != nil { - return nil, err - } - - if len(resp.TimeStampToken.Bytes) == 0 { - return nil, errors.New("no pkcs7 data in Time-Stamp response") - } - - timestamp_attribute := pkcs7.Attribute{ - Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 2, 14}, - Value: resp.TimeStampToken, - } - signer_config.ExtraUnsignedAttributes = append(signer_config.ExtraUnsignedAttributes, timestamp_attribute) - - tsa_certificate_pool := x509.NewCertPool() - for _, certificate := range timestamp_p7.Certificates { - tsa_certificate_pool.AddCert(certificate) - } - - if len(timestamp_p7.Certificates) > 0 { - TSATokenChain, err = timestamp_p7.Certificates[len(timestamp_p7.Certificates)-1].Verify(x509.VerifyOptions{ - Intermediates: tsa_certificate_pool, - }) - } - } - if context.SignData.RevocationFunction != nil { if context.SignData.CertificateChains != nil && (len(context.SignData.CertificateChains) > 0) { certificate_chain := context.SignData.CertificateChains[0] @@ -217,6 +171,43 @@ func (context *SignContext) createSignature() ([]byte, error) { // PDF needs a detached signature, meaning the content isn't included. signed_data.Detach() + if context.SignData.TSA.URL != "" { + signature_data := signed_data.GetSignedData() + + timestamp_response, err := context.GetTSA(signature_data.SignerInfos[0].EncryptedDigest) + if err != nil { + return nil, err + } + + var rest []byte + var resp TSAResponse + if rest, err = asn1.Unmarshal(timestamp_response, &resp); err != nil { + return nil, err + } + if len(rest) > 0 { + return nil, errors.New("trailing data in Time-Stamp response") + } + + if resp.Status.Status > 0 { + return nil, errors.New(fmt.Sprintf("%s: %s", timestamp.FailureInfo(resp.Status.FailInfo).String(), resp.Status.StatusString)) + } + + _, err = pkcs7.Parse(resp.TimeStampToken.FullBytes) + if err != nil { + return nil, err + } + + if len(resp.TimeStampToken.Bytes) == 0 { + return nil, errors.New("no pkcs7 data in Time-Stamp response") + } + + timestamp_attribute := pkcs7.Attribute{ + Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 2, 14}, + Value: resp.TimeStampToken, + } + signature_data.SignerInfos[0].SetUnauthenticatedAttributes([]pkcs7.Attribute{timestamp_attribute}) + } + return signed_data.Finish() } diff --git a/verify/verify.go b/verify/verify.go index e713c8e..06b7e89 100644 --- a/verify/verify.go +++ b/verify/verify.go @@ -16,6 +16,7 @@ import ( "github.com/digitorus/timestamp" "log" "golang.org/x/crypto/ocsp" + "crypto" ) type Response struct { @@ -147,6 +148,22 @@ func Verify(file *os.File) (apiResp *Response, err error) { apiResp.Error = fmt.Sprintln("Failed to parse timestamp", err) } + r := bytes.NewReader(s.EncryptedDigest) + h := crypto.SHA256.New() + b := make([]byte, 32) + for { + n, err := r.Read(b) + if err == io.EOF { + break + } + + h.Write(b[:n]) + } + + if !bytes.Equal(h.Sum(nil), signer.TimeStamp.HashedMessage) { + apiResp.Error = fmt.Sprintln("Hash in timestamp is different from pkcs7") + } + break } } @@ -217,7 +234,7 @@ func Verify(file *os.File) (apiResp *Response, err error) { signer.RevokedCertificate = true } - if len(chain) > 1 && len(chain[0]) > 1 { + if len(chain) > 0 && len(chain[0]) > 1 { issuer := chain[0][1] if resp.Certificate != nil { err = resp.Certificate.CheckSignatureFrom(issuer)