DigestAlgorithm & SigningCertificate attribute

This commit is contained in:
Paul van Brouwershaven
2022-07-15 15:42:10 +02:00
parent 6224a363e9
commit dcc44d5779
5 changed files with 76 additions and 2 deletions

View File

@@ -71,8 +71,9 @@ err = sign.Sign(input_file, output_file, rdr, size, sign.SignData{
CertType: sign.CertificationSignature, CertType: sign.CertificationSignature,
DocMDPPerm: sign.AllowFillingExistingFormFieldsAndSignaturesPerms, DocMDPPerm: sign.AllowFillingExistingFormFieldsAndSignaturesPerms,
}, },
Signer: privateKey, // crypto.Signer Signer: privateKey, // crypto.Signer
Certificate: certificate, // x509.Certificate DigestAlgorithm: crypto.SHA256, // hash algorithm for the digest creation
Certificate: certificate, // x509.Certificate
CertificateChains: certificate_chains, // x509.Certificate.Verify() CertificateChains: certificate_chains, // x509.Certificate.Verify()
TSA: sign.TSA{ TSA: sign.TSA{
URL: "https://freetsa.org/tsr", URL: "https://freetsa.org/tsr",

View File

@@ -1,6 +1,7 @@
package main package main
import ( import (
"crypto"
"flag" "flag"
"fmt" "fmt"
"log" "log"
@@ -142,6 +143,7 @@ func main() {
DocMDPPerm: sign.AllowFillingExistingFormFieldsAndSignaturesPerms, DocMDPPerm: sign.AllowFillingExistingFormFieldsAndSignaturesPerms,
}, },
Signer: pkey, Signer: pkey,
DigestAlgorithm: crypto.SHA256,
Certificate: cert, Certificate: cert,
CertificateChains: certificate_chains, CertificateChains: certificate_chains,
TSA: sign.TSA{ TSA: sign.TSA{

View File

@@ -1,6 +1,8 @@
package sign package sign
import ( import (
"crypto"
"encoding/asn1"
"errors" "errors"
"fmt" "fmt"
"io" "io"
@@ -140,3 +142,28 @@ func writePartFromSourceFileToTargetFile(input_file io.ReadSeeker, output_file i
return nil return nil
} }
var hashOIDs = map[crypto.Hash]asn1.ObjectIdentifier{
crypto.SHA1: asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}),
crypto.SHA256: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1}),
crypto.SHA384: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2}),
crypto.SHA512: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3}),
}
func getHashAlgorithmFromOID(target asn1.ObjectIdentifier) crypto.Hash {
for hash, oid := range hashOIDs {
if oid.Equal(target) {
return hash
}
}
return crypto.Hash(0)
}
func getOIDFromHashAlgorithm(target crypto.Hash) asn1.ObjectIdentifier {
for hash, oid := range hashOIDs {
if hash == target {
return oid
}
}
return nil
}

View File

@@ -2,6 +2,7 @@ package sign
import ( import (
"bytes" "bytes"
"crypto"
"crypto/x509" "crypto/x509"
"encoding/asn1" "encoding/asn1"
"encoding/hex" "encoding/hex"
@@ -13,6 +14,8 @@ import (
"github.com/digitorus/pkcs7" "github.com/digitorus/pkcs7"
"github.com/digitorus/timestamp" "github.com/digitorus/timestamp"
"golang.org/x/crypto/cryptobyte"
cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1"
) )
const signatureByteRangePlaceholder = "/ByteRange[0 ********** ********** **********]" const signatureByteRangePlaceholder = "/ByteRange[0 ********** ********** **********]"
@@ -121,6 +124,39 @@ func (context *SignContext) fetchRevocationData() error {
return nil return nil
} }
func (context *SignContext) createSigningCertificateAttribute() (*pkcs7.Attribute, error) {
hash := context.SignData.DigestAlgorithm.New()
hash.Write(context.SignData.Certificate.Raw)
var b cryptobyte.Builder
b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { // SigningCertificate
b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { // []ESSCertID, []ESSCertIDv2
b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { // ESSCertID, ESSCertIDv2
if context.SignData.DigestAlgorithm.HashFunc() != crypto.SHA1 &&
context.SignData.DigestAlgorithm.HashFunc() != crypto.SHA256 { // default SHA-256
b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { // AlgorithmIdentifier
b.AddASN1ObjectIdentifier(getOIDFromHashAlgorithm(context.SignData.DigestAlgorithm))
})
}
b.AddASN1OctetString(hash.Sum(nil)) // certHash
})
})
})
sse, err := b.Bytes()
if err != nil {
return nil, err
}
signingCertificate := pkcs7.Attribute{
Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 2, 47}, // SigningCertificateV2
Value: asn1.RawValue{FullBytes: sse},
}
if context.SignData.DigestAlgorithm.HashFunc() == crypto.SHA1 {
signingCertificate.Type = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 2, 12} // SigningCertificate
}
return &signingCertificate, nil
}
func (context *SignContext) createSignature() ([]byte, error) { func (context *SignContext) createSignature() ([]byte, error) {
if _, err := context.OutputBuffer.Seek(0, 0); err != nil { if _, err := context.OutputBuffer.Seek(0, 0); err != nil {
return nil, err return nil, err
@@ -140,12 +176,19 @@ func (context *SignContext) createSignature() ([]byte, error) {
return nil, fmt.Errorf("new signed data: %w", err) return nil, fmt.Errorf("new signed data: %w", err)
} }
signed_data.SetDigestAlgorithm(getOIDFromHashAlgorithm(context.SignData.DigestAlgorithm))
signingCertificate, err := context.createSigningCertificateAttribute()
if err != nil {
return nil, fmt.Errorf("new signed data: %w", err)
}
signer_config := pkcs7.SignerInfoConfig{ signer_config := pkcs7.SignerInfoConfig{
ExtraSignedAttributes: []pkcs7.Attribute{ ExtraSignedAttributes: []pkcs7.Attribute{
{ {
Type: asn1.ObjectIdentifier{1, 2, 840, 113583, 1, 1, 8}, Type: asn1.ObjectIdentifier{1, 2, 840, 113583, 1, 1, 8},
Value: context.SignData.RevocationData, Value: context.SignData.RevocationData,
}, },
*signingCertificate,
}, },
} }

View File

@@ -34,6 +34,7 @@ type SignData struct {
ObjectId uint32 ObjectId uint32
Signature SignDataSignature Signature SignDataSignature
Signer crypto.Signer Signer crypto.Signer
DigestAlgorithm crypto.Hash
Certificate *x509.Certificate Certificate *x509.Certificate
CertificateChains [][]*x509.Certificate CertificateChains [][]*x509.Certificate
TSA TSA TSA TSA