Add revocation information
This commit is contained in:
19
certificate.pem
Normal file
19
certificate.pem
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDBDCCAm2gAwIBAgIJAP6vkkLP72OOMA0GCSqGSIb3DQEBCwUAMIGZMQswCQYD
|
||||||
|
VQQGEwJOTDEVMBMGA1UECAwMWnVpZC1Ib2xsYW5kMRIwEAYDVQQHDAlSb3R0ZXJk
|
||||||
|
YW0xEjAQBgNVBAoMCVVuaWNvZGVyczELMAkGA1UECwwCSVQxGjAYBgNVBAMMEUpl
|
||||||
|
cm9lbiBCb2JiZWxkaWprMSIwIAYJKoZIhvcNAQkBFhNqZXJvZW5AdW5pY29kZXJz
|
||||||
|
Lm5sMCAXDTE3MDcwNjE5MzYwOVoYDzMwMTYxMTA2MTkzNjA5WjCBmTELMAkGA1UE
|
||||||
|
BhMCTkwxFTATBgNVBAgMDFp1aWQtSG9sbGFuZDESMBAGA1UEBwwJUm90dGVyZGFt
|
||||||
|
MRIwEAYDVQQKDAlVbmljb2RlcnMxCzAJBgNVBAsMAklUMRowGAYDVQQDDBFKZXJv
|
||||||
|
ZW4gQm9iYmVsZGlqazEiMCAGCSqGSIb3DQEJARYTamVyb2VuQHVuaWNvZGVycy5u
|
||||||
|
bDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArpfaVUltYdOSISuc8V5vAy6b
|
||||||
|
jpqYuxsS5I6jpL1nMKms9IB5+uk+Glo2O/tb+W/R8zxQ3xrQ6JWZ4ZSsBhKNVink
|
||||||
|
Su3+kdAQJfHn3NLJzx0QGceo0TF2RvVGo5c91zxuA8rchdNz1QxrD6QesGKyfsXn
|
||||||
|
F+oELezafT346PbeqikCAwEAAaNQME4wHQYDVR0OBBYEFKA68BB0iwhY2RIRFIYs
|
||||||
|
gmq0l6y7MB8GA1UdIwQYMBaAFKA68BB0iwhY2RIRFIYsgmq0l6y7MAwGA1UdEwQF
|
||||||
|
MAMBAf8wDQYJKoZIhvcNAQELBQADgYEAZ75HjcE/d/nclPTQbCN9qvUyuU76ml4O
|
||||||
|
jDN8T+loOsUKmI4VVsNLzF6DXq8sg4EP7s8kEEzM7qhoijw09OUhVniBYN3SzJYX
|
||||||
|
l8AiThPGqcIm1TrkqPULYQBu/FnMoL6SP7kAULcsUvEmn1rPcG9ESQ4sK/ceJhFZ
|
||||||
|
zk9o3rVC0PU=
|
||||||
|
-----END CERTIFICATE-----
|
@@ -1,8 +1,8 @@
|
|||||||
package revocation
|
package revocation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/x509"
|
||||||
"encoding/asn1"
|
"encoding/asn1"
|
||||||
"crypto/x509"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// InfoArchival is the pkcs7 container containing the revocation information for
|
// InfoArchival is the pkcs7 container containing the revocation information for
|
||||||
@@ -21,13 +21,13 @@ type InfoArchival struct {
|
|||||||
// pass the bytes of a downloaded CRL to this function.
|
// pass the bytes of a downloaded CRL to this function.
|
||||||
func (r *InfoArchival) AddCRL(b []byte) error {
|
func (r *InfoArchival) AddCRL(b []byte) error {
|
||||||
r.CRL = append(r.CRL, asn1.RawValue{FullBytes: b})
|
r.CRL = append(r.CRL, asn1.RawValue{FullBytes: b})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddOCSP is used to embed the raw bytes of an OCSP response.
|
// AddOCSP is used to embed the raw bytes of an OCSP response.
|
||||||
func (r *InfoArchival) AddOCSP(b []byte) error {
|
func (r *InfoArchival) AddOCSP(b []byte) error {
|
||||||
r.OCSP = append(r.OCSP, asn1.RawValue{FullBytes: b})
|
r.OCSP = append(r.OCSP, asn1.RawValue{FullBytes: b})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRevoked checks if there is a status inclded for the certificate and returns
|
// IsRevoked checks if there is a status inclded for the certificate and returns
|
||||||
@@ -37,7 +37,7 @@ func (r *InfoArchival) AddOCSP(b []byte) error {
|
|||||||
// TODO: Information about the revocation (time, reason, etc) must be extractable
|
// TODO: Information about the revocation (time, reason, etc) must be extractable
|
||||||
func (r *InfoArchival) IsRevoked(c *x509.Certificate) bool {
|
func (r *InfoArchival) IsRevoked(c *x509.Certificate) bool {
|
||||||
// check the crl and ocsp to see if this certificate is revoked
|
// check the crl and ocsp to see if this certificate is revoked
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// CRL contains the raw bytes of a pkix.CertificateList and can be parsed with
|
// CRL contains the raw bytes of a pkix.CertificateList and can be parsed with
|
||||||
|
5
sign.go
5
sign.go
@@ -11,6 +11,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
|
"bitbucket.org/digitorus/pdfsign/revocation"
|
||||||
"bitbucket.org/digitorus/pdfsign/sign"
|
"bitbucket.org/digitorus/pdfsign/sign"
|
||||||
"bitbucket.org/digitorus/pdfsign/verify"
|
"bitbucket.org/digitorus/pdfsign/verify"
|
||||||
)
|
)
|
||||||
@@ -104,8 +105,10 @@ func main() {
|
|||||||
Signer: pkey,
|
Signer: pkey,
|
||||||
Certificate: cert,
|
Certificate: cert,
|
||||||
TSA: sign.TSA{
|
TSA: sign.TSA{
|
||||||
URL: "http://aatl-timestamp.globalsign.com/tsa/aohfewat2389535fnasgnlg5m23",
|
URL: "http://aatl-timestamp.globalsign.com/tsa/aohfewat2389535fnasgnlg5m23",
|
||||||
},
|
},
|
||||||
|
RevocationData: revocation.InfoArchival{},
|
||||||
|
RevocationFunction: sign.DefaultEmbedRevocationStatusFunction,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
|
@@ -135,12 +135,33 @@ func (context *SignContext) createSignature() ([]byte, error) {
|
|||||||
Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 2, 14},
|
Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 2, 14},
|
||||||
Value: resp.TimeStampToken,
|
Value: resp.TimeStampToken,
|
||||||
}
|
}
|
||||||
signer_config.ExtraUnsignedAttributes = append(signer_config.ExtraSignedAttributes, timestamp_attribute)
|
signer_config.ExtraUnsignedAttributes = append(signer_config.ExtraUnsignedAttributes, timestamp_attribute)
|
||||||
|
}
|
||||||
|
|
||||||
|
if context.SignData.RevocationFunction != nil {
|
||||||
|
err = context.SignData.RevocationFunction(context.SignData.Certificate, nil, &context.SignData.RevocationData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if context.SignData.CertificateChain != nil && len(context.SignData.CertificateChain) > 0 {
|
||||||
|
for _, cert := range context.SignData.CertificateChain {
|
||||||
|
err = context.SignData.RevocationFunction(cert, nil, &context.SignData.RevocationData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
revocation_attribute := pkcs7.Attribute{
|
||||||
|
Type: asn1.ObjectIdentifier{1, 2, 840, 113583, 1, 1, 8},
|
||||||
|
Value: context.SignData.RevocationData,
|
||||||
|
}
|
||||||
|
signer_config.ExtraSignedAttributes = append(signer_config.ExtraSignedAttributes, revocation_attribute)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the signer and sign the data.
|
// Add the signer and sign the data.
|
||||||
if err := signed_data.AddSignerChain(context.SignData.Certificate, context.SignData.Signer, context.SignData.CertificateChain, signer_config); err != nil {
|
if err := signed_data.AddSignerChain(context.SignData.Certificate, context.SignData.Signer, context.SignData.CertificateChain, signer_config); err != nil {
|
||||||
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,7 +3,6 @@ package sign
|
|||||||
import (
|
import (
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -38,8 +37,7 @@ func embedOCSPRevocationStatus(cert, issuer *x509.Certificate, i *revocation.Inf
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
i.AddOCSP(body)
|
return i.AddOCSP(body)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// embedCRLRevocationStatus requires an issuer as it needs to implement the
|
// embedCRLRevocationStatus requires an issuer as it needs to implement the
|
||||||
@@ -56,11 +54,10 @@ func embedCRLRevocationStatus(cert, issuer *x509.Certificate, i *revocation.Info
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: verify crl and certificate before embedding
|
// TODO: verify crl and certificate before embedding
|
||||||
i.AddCRL(body)
|
return i.AddCRL(body)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func embedRevocationStatus(cert, issuer *x509.Certificate, i *revocation.InfoArchival) error {
|
func DefaultEmbedRevocationStatusFunction(cert, issuer *x509.Certificate, i *revocation.InfoArchival) error {
|
||||||
// For each certificate a revoction status needs to be included, this can be done
|
// For each certificate a revoction status needs to be included, this can be done
|
||||||
// by embedding a CRL or OCSP response. In most cases an OCSP response is smaller
|
// by embedding a CRL or OCSP response. In most cases an OCSP response is smaller
|
||||||
// to embed in the document but and empty CRL (often seen of dediced high volume
|
// to embed in the document but and empty CRL (often seen of dediced high volume
|
||||||
@@ -74,15 +71,19 @@ func embedRevocationStatus(cert, issuer *x509.Certificate, i *revocation.InfoArc
|
|||||||
|
|
||||||
// using an OCSP server
|
// using an OCSP server
|
||||||
if len(cert.OCSPServer) > 0 {
|
if len(cert.OCSPServer) > 0 {
|
||||||
embedOCSPRevocationStatus(cert, issuer, i)
|
err := embedOCSPRevocationStatus(cert, issuer, i)
|
||||||
return nil
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// using a crl
|
// using a crl
|
||||||
if len(cert.CRLDistributionPoints) > 0 {
|
if len(cert.CRLDistributionPoints) > 0 {
|
||||||
embedCRLRevocationStatus(cert, issuer, i)
|
err := embedCRLRevocationStatus(cert, issuer, i)
|
||||||
return nil
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.New("certificate contains no information to check status")
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -75,7 +75,7 @@ htN+laG7bS/8xGTPothL9Abgd/9L3X0KKGUDCdcpzRuy20CI7E4uygD8
|
|||||||
func TestEmbedRevocationStatus(t *testing.T) {
|
func TestEmbedRevocationStatus(t *testing.T) {
|
||||||
var ia revocation.InfoArchival
|
var ia revocation.InfoArchival
|
||||||
|
|
||||||
err := embedRevocationStatus(pemToCert(certPem), pemToCert(issuerPem), &ia)
|
err := DefaultEmbedRevocationStatusFunction(pemToCert(certPem), pemToCert(issuerPem), &ia)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s", err.Error())
|
t.Errorf("%s", err.Error())
|
||||||
}
|
}
|
||||||
|
23
sign/sign.go
23
sign/sign.go
@@ -8,6 +8,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/digitorus/pdf"
|
"bitbucket.org/digitorus/pdf"
|
||||||
|
"bitbucket.org/digitorus/pdfsign/revocation"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CatalogData struct {
|
type CatalogData struct {
|
||||||
@@ -17,18 +18,22 @@ type CatalogData struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TSA struct {
|
type TSA struct {
|
||||||
URL string
|
URL string
|
||||||
Username string
|
Username string
|
||||||
Password string
|
Password string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RevocationFunction func(cert, issuer *x509.Certificate, i *revocation.InfoArchival) error
|
||||||
|
|
||||||
type SignData struct {
|
type SignData struct {
|
||||||
ObjectId uint32
|
ObjectId uint32
|
||||||
Signature SignDataSignature
|
Signature SignDataSignature
|
||||||
Signer crypto.Signer
|
Signer crypto.Signer
|
||||||
Certificate *x509.Certificate
|
Certificate *x509.Certificate
|
||||||
CertificateChain []*x509.Certificate
|
CertificateChain []*x509.Certificate
|
||||||
TSA TSA
|
TSA TSA
|
||||||
|
RevocationData revocation.InfoArchival
|
||||||
|
RevocationFunction RevocationFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
type VisualSignData struct {
|
type VisualSignData struct {
|
||||||
|
Reference in New Issue
Block a user