Use timestamp package for TSA
This commit is contained in:
@@ -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