go_S-MIME/timestamp/info.go

100 lines
3.4 KiB
Go

package timestamp
import (
"crypto/x509/pkix"
"encoding/asn1"
"math/big"
"time"
asn "git.ma-al.com/goc_marek/go_S-MIME/asn1"
cms "git.ma-al.com/goc_marek/go_S-MIME/cms/protocol"
oid "git.ma-al.com/goc_marek/go_S-MIME/oid"
)
// TSTInfo ::= SEQUENCE {
// version INTEGER { v1(1) },
// policy TSAPolicyId,
// messageImprint MessageImprint,
// -- MUST have the same value as the similar field in
// -- TimeStampReq
// serialNumber INTEGER,
// -- Time-Stamping users MUST be ready to accommodate integers
// -- up to 160 bits.
// genTime GeneralizedTime,
// accuracy Accuracy OPTIONAL,
// ordering BOOLEAN DEFAULT FALSE,
// nonce INTEGER OPTIONAL,
// -- MUST be present if the similar field was present
// -- in TimeStampReq. In that case it MUST have the same value.
// tsa [0] GeneralName OPTIONAL,
// extensions [1] IMPLICIT Extensions OPTIONAL }
type TSTInfo struct {
Version int
Policy asn1.ObjectIdentifier
MessageImprint MessageImprint
SerialNumber *big.Int
GenTime time.Time `asn1:"generalized"`
Accuracy Accuracy `asn1:"optional"`
Ordering bool `asn1:"optional,default:false"`
Nonce *big.Int `asn1:"optional"`
TSA asn1.RawValue `asn1:"tag:0,optional"`
Extensions []pkix.Extension `asn1:"tag:1,optional"`
}
// ParseInfo parses an Info out of a CMS EncapsulatedContentInfo.
func ParseInfo(enci cms.EncapsulatedContentInfo) (TSTInfo, error) {
i := TSTInfo{}
if !enci.EContentType.Equal(oid.TSTInfo) {
return i, cms.ErrWrongType
}
if rest, err := asn.Unmarshal(enci.EContent, &i); err != nil {
return i, err
} else if len(rest) > 0 {
return i, cms.ErrTrailingData
}
return i, nil
}
// Before checks if the latest time the signature could have been generated at
// is before the specified time. For example, you might check that a signature
// was made *before* a certificate's not-after date.
func (i *TSTInfo) Before(t time.Time) bool {
return i.genTimeMax().Before(t)
}
// After checks if the earlier time the signature could have been generated at
// is before the specified time. For example, you might check that a signature
// was made *after* a certificate's not-before date.
func (i *TSTInfo) After(t time.Time) bool {
return i.genTimeMin().After(t)
}
// genTimeMax is the latest time at which the token could have been generated
// based on the included GenTime and Accuracy attributes.
func (i *TSTInfo) genTimeMax() time.Time {
return i.GenTime.Add(i.Accuracy.Duration())
}
// genTimeMin is the earliest time at which the token could have been generated
// based on the included GenTime and Accuracy attributes.
func (i *TSTInfo) genTimeMin() time.Time {
return i.GenTime.Add(-i.Accuracy.Duration())
}
// Accuracy of the timestamp
type Accuracy struct {
Seconds int `asn1:"optional"`
Millis int `asn1:"tag:0,optional"`
Micros int `asn1:"tag:1,optional"`
}
// Duration returns this Accuracy as a time.Duration.
func (a Accuracy) Duration() time.Duration {
return 0 +
time.Duration(a.Seconds)*time.Second +
time.Duration(a.Millis)*time.Millisecond +
time.Duration(a.Micros)*time.Microsecond
}