Use timestamp package for TSA
This commit is contained in:
2
go.mod
2
go.mod
@@ -5,7 +5,7 @@ go 1.17
|
||||
require (
|
||||
github.com/digitorus/pdf v0.1.2
|
||||
github.com/digitorus/pkcs7 v0.0.0-20200320092839-808436b6f6d1
|
||||
github.com/digitorus/timestamp v0.0.0-20210102082646-54ddd7720e27
|
||||
github.com/digitorus/timestamp v0.0.0-20220630150916-a1b00e34b289
|
||||
github.com/mattetti/filebuffer v1.0.1
|
||||
golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70
|
||||
)
|
||||
|
4
go.sum
4
go.sum
@@ -8,6 +8,10 @@ github.com/digitorus/pkcs7 v0.0.0-20200320092839-808436b6f6d1 h1:V1cgDSp4Kq4eMCf
|
||||
github.com/digitorus/pkcs7 v0.0.0-20200320092839-808436b6f6d1/go.mod h1:p2IZ9yq2kEKGFr3rfpYxaaOzB0VdLbF8VkZReEIpJmU=
|
||||
github.com/digitorus/timestamp v0.0.0-20210102082646-54ddd7720e27 h1:X8tvQGATvS7vQBAPPn0f7nQPcTamu4ecCbRafPrBgik=
|
||||
github.com/digitorus/timestamp v0.0.0-20210102082646-54ddd7720e27/go.mod h1:IKw2TcDeMaZrNjpdq7gPc7I+a21+Sn34bUqWrTc70Hs=
|
||||
github.com/digitorus/timestamp v0.0.0-20220630080933-558840f252f5 h1:zYpNMBe+1x3h0FMTJThci7KimEldiiOrn0ENMP6+I/8=
|
||||
github.com/digitorus/timestamp v0.0.0-20220630080933-558840f252f5/go.mod h1:IKw2TcDeMaZrNjpdq7gPc7I+a21+Sn34bUqWrTc70Hs=
|
||||
github.com/digitorus/timestamp v0.0.0-20220630150916-a1b00e34b289 h1:WIoYZV4zZKwIymytM65i+WgqyTN/ElCf7KddV01C+0s=
|
||||
github.com/digitorus/timestamp v0.0.0-20220630150916-a1b00e34b289/go.mod h1:IKw2TcDeMaZrNjpdq7gPc7I+a21+Sn34bUqWrTc70Hs=
|
||||
github.com/mattetti/filebuffer v1.0.1 h1:gG7pyfnSIZCxdoKq+cPa8T0hhYtD9NxCdI4D7PTjRLM=
|
||||
github.com/mattetti/filebuffer v1.0.1/go.mod h1:YdMURNDOttIiruleeVr6f56OrMc+MydEnTcXwtkxNVs=
|
||||
golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU=
|
||||
|
@@ -15,18 +15,6 @@ import (
|
||||
"github.com/digitorus/timestamp"
|
||||
)
|
||||
|
||||
type pkiStatusInfo struct {
|
||||
Status int
|
||||
StatusString string `asn1:"optional"`
|
||||
FailInfo int `asn1:"optional"`
|
||||
}
|
||||
|
||||
// 2.4.2. Response Format
|
||||
type TSAResponse struct {
|
||||
Status pkiStatusInfo
|
||||
TimeStampToken asn1.RawValue
|
||||
}
|
||||
|
||||
var signatureByteRangePlaceholder = "/ByteRange[0 ********** ********** **********]"
|
||||
|
||||
func (context *SignContext) createSignaturePlaceholder() (dssd string, byte_range_start_byte int64, signature_contents_start_byte int64) {
|
||||
@@ -134,7 +122,9 @@ func (context *SignContext) fetchRevocationData() error {
|
||||
}
|
||||
|
||||
func (context *SignContext) createSignature() ([]byte, error) {
|
||||
context.OutputBuffer.Seek(0, 0)
|
||||
if _, err := context.OutputBuffer.Seek(0, 0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Sadly we can't efficiently sign a file, we need to read all the bytes we want to sign.
|
||||
file_content := context.OutputBuffer.Buff.Bytes()
|
||||
@@ -147,7 +137,7 @@ func (context *SignContext) createSignature() ([]byte, error) {
|
||||
// Initialize pkcs7 signer.
|
||||
signed_data, err := pkcs7.NewSignedData(sign_content)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("new signed data: %w", err)
|
||||
}
|
||||
|
||||
signer_config := pkcs7.SignerInfoConfig{
|
||||
@@ -167,7 +157,7 @@ func (context *SignContext) createSignature() ([]byte, error) {
|
||||
|
||||
// Add the signer and sign the data.
|
||||
if err := signed_data.AddSignerChain(context.SignData.Certificate, context.SignData.Signer, certificate_chain, signer_config); err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("add signer chain: %w", err)
|
||||
}
|
||||
|
||||
// PDF needs a detached signature, meaning the content isn't included.
|
||||
@@ -178,36 +168,26 @@ func (context *SignContext) createSignature() ([]byte, error) {
|
||||
|
||||
timestamp_response, err := context.GetTSA(signature_data.SignerInfos[0].EncryptedDigest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("get timestamp: %w", 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)
|
||||
ts, err := timestamp.ParseResponse(timestamp_response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("parse timestamp: %w", err)
|
||||
}
|
||||
|
||||
if len(resp.TimeStampToken.Bytes) == 0 {
|
||||
return nil, errors.New("no pkcs7 data in Time-Stamp response")
|
||||
_, err = pkcs7.Parse(ts.RawToken)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse timestamp token: %w", err)
|
||||
}
|
||||
|
||||
timestamp_attribute := pkcs7.Attribute{
|
||||
Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 2, 14},
|
||||
Value: resp.TimeStampToken,
|
||||
Value: asn1.RawValue{FullBytes: ts.RawToken},
|
||||
}
|
||||
if err := signature_data.SignerInfos[0].SetUnauthenticatedAttributes([]pkcs7.Attribute{timestamp_attribute}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
signature_data.SignerInfos[0].SetUnauthenticatedAttributes([]pkcs7.Attribute{timestamp_attribute})
|
||||
}
|
||||
|
||||
return signed_data.Finish()
|
||||
@@ -219,13 +199,13 @@ func (context *SignContext) GetTSA(sign_content []byte) (timestamp_response []by
|
||||
Certificates: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||
}
|
||||
|
||||
ts_request_reader := bytes.NewReader(ts_request)
|
||||
req, err := http.NewRequest("POST", context.SignData.TSA.URL, ts_request_reader)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error requesting timestamp (%s): %w", context.SignData.TSA.URL, err)
|
||||
return nil, fmt.Errorf("failed to prepare request (%s): %w", context.SignData.TSA.URL, err)
|
||||
}
|
||||
|
||||
req.Header.Add("Content-Type", "application/timestamp-query")
|
||||
@@ -247,18 +227,16 @@ func (context *SignContext) GetTSA(sign_content []byte) (timestamp_response []by
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
err = errors.New("non success response (" + strconv.Itoa(code) + "): " + string(body))
|
||||
} else {
|
||||
err = errors.New("non success response (" + strconv.Itoa(code) + ")")
|
||||
return nil, errors.New("non success response (" + strconv.Itoa(code) + "): " + string(body))
|
||||
}
|
||||
|
||||
return nil, err
|
||||
return nil, errors.New("non success response (" + strconv.Itoa(code) + ")")
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
timestamp_response_body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed to read response: %w", err)
|
||||
}
|
||||
|
||||
return timestamp_response_body, nil
|
||||
@@ -267,7 +245,7 @@ func (context *SignContext) GetTSA(sign_content []byte) (timestamp_response []by
|
||||
func (context *SignContext) replaceSignature() error {
|
||||
signature, err := context.createSignature()
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to create signature: %w", err)
|
||||
}
|
||||
|
||||
dst := make([]byte, hex.EncodedLen(len(signature)))
|
||||
@@ -280,17 +258,23 @@ func (context *SignContext) replaceSignature() error {
|
||||
return context.SignPDF()
|
||||
}
|
||||
|
||||
context.OutputBuffer.Seek(0, 0)
|
||||
if _, err := context.OutputBuffer.Seek(0, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
file_content := context.OutputBuffer.Buff.Bytes()
|
||||
|
||||
context.OutputBuffer.Write(file_content[:(context.ByteRangeValues[0] + context.ByteRangeValues[1] + 1)])
|
||||
if _, err := context.OutputBuffer.Write(file_content[:(context.ByteRangeValues[0] + context.ByteRangeValues[1] + 1)]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write new ByteRange.
|
||||
if _, err := context.OutputBuffer.Write([]byte(dst)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
context.OutputBuffer.Write(file_content[(context.ByteRangeValues[0]+context.ByteRangeValues[1]+1)+int64(len(dst)):])
|
||||
if _, err := context.OutputBuffer.Write(file_content[(context.ByteRangeValues[0]+context.ByteRangeValues[1]+1)+int64(len(dst)):]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user