@ -6,9 +6,8 @@ import (
"crypto/ecdsa"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/elliptic"
"crypto/rsa"
"crypto/rsa"
"crypto/x509"
"encoding/asn1"
"errors"
"errors"
"math/big"
"time"
"time"
"g.activething.com/go/DateKeys/internal/der"
"g.activething.com/go/DateKeys/internal/der"
@ -29,15 +28,19 @@ const (
)
)
var (
var (
oidRSAEncryption = asn1 . ObjectIdentifier { 1 , 2 , 840 , 113549 , 1 , 1 , 1 }
oidRSAEncryption = oid ( "1.2.840.113549.1.1.1" )
oidSHA256RSA = asn1 . ObjectIdentifier { 1 , 2 , 840 , 113549 , 1 , 1 , 11 }
oidSHA256RSA = oid ( "1.2.840.113549.1.1.11" )
oidSHA384RSA = asn1 . ObjectIdentifier { 1 , 2 , 840 , 113549 , 1 , 1 , 12 }
oidSHA384RSA = oid ( "1.2.840.113549.1.1.12" )
oidSHA512RSA = asn1 . ObjectIdentifier { 1 , 2 , 840 , 113549 , 1 , 1 , 13 }
oidSHA512RSA = oid ( "1.2.840.113549.1.1.13" )
oidPSS = asn1 . ObjectIdentifier { 1 , 2 , 840 , 113549 , 1 , 1 , 10 }
oidPSS = oid ( "1.2.840.113549.1.1.10" )
oidMGF1 = asn1 . ObjectIdentifier { 1 , 2 , 840 , 113549 , 1 , 1 , 8 }
oidMGF1 = oid ( "1.2.840.113549.1.1.8" )
oidECDSA256 = asn1 . ObjectIdentifier { 1 , 2 , 840 , 10045 , 4 , 3 , 2 }
oidECDSA256 = oid ( "1.2.840.10045.4.3.2" )
oidECDSA384 = asn1 . ObjectIdentifier { 1 , 2 , 840 , 10045 , 4 , 3 , 3 }
oidECDSA384 = oid ( "1.2.840.10045.4.3.3" )
oidECDSA512 = asn1 . ObjectIdentifier { 1 , 2 , 840 , 10045 , 4 , 3 , 4 }
oidECDSA512 = oid ( "1.2.840.10045.4.3.4" )
oidECPublicKey = oid ( "1.2.840.10045.2.1" )
oidP256 = oid ( "1.2.840.10045.3.1.7" )
oidP384 = oid ( "1.3.132.0.34" )
oidP521 = oid ( "1.3.132.0.35" )
)
)
type scheme int
type scheme int
@ -65,24 +68,24 @@ func (s *SignerInfo) params() (crypto.Hash, scheme, bool) {
default :
default :
h = crypto . SHA512
h = crypto . SHA512
}
}
o id , params := s . SigAlg . OID , s . SigAlg . Params
o , params := s . SigAlg . OID , s . SigAlg . Params
nullOrAbsent := params == nil || bytes . Equal ( params , [ ] byte { 5 , 0 } )
nullOrAbsent := params == nil || bytes . Equal ( params , [ ] byte { 5 , 0 } )
switch {
switch {
case oid. Equal ( oidRSAEncryption ) :
case bytes. Equal ( o , oidRSAEncryption ) :
return h , schemePKCS1 , nullOrAbsent
return h , schemePKCS1 , nullOrAbsent
case oid. Equal ( oidSHA256RSA ) :
case bytes. Equal ( o , oidSHA256RSA ) :
return h , schemePKCS1 , nullOrAbsent && h == crypto . SHA256
return h , schemePKCS1 , nullOrAbsent && h == crypto . SHA256
case oid. Equal ( oidSHA384RSA ) :
case bytes. Equal ( o , oidSHA384RSA ) :
return h , schemePKCS1 , nullOrAbsent && h == crypto . SHA384
return h , schemePKCS1 , nullOrAbsent && h == crypto . SHA384
case oid. Equal ( oidSHA512RSA ) :
case bytes. Equal ( o , oidSHA512RSA ) :
return h , schemePKCS1 , nullOrAbsent && h == crypto . SHA512
return h , schemePKCS1 , nullOrAbsent && h == crypto . SHA512
case oid. Equal ( oidECDSA256 ) :
case bytes. Equal ( o , oidECDSA256 ) :
return h , schemeECDSA , params == nil && h == crypto . SHA256
return h , schemeECDSA , params == nil && h == crypto . SHA256
case oid. Equal ( oidECDSA384 ) :
case bytes. Equal ( o , oidECDSA384 ) :
return h , schemeECDSA , params == nil && h == crypto . SHA384
return h , schemeECDSA , params == nil && h == crypto . SHA384
case oid. Equal ( oidECDSA512 ) :
case bytes. Equal ( o , oidECDSA512 ) :
return h , schemeECDSA , params == nil && h == crypto . SHA512
return h , schemeECDSA , params == nil && h == crypto . SHA512
case oid. Equal ( oidPSS ) :
case bytes. Equal ( o , oidPSS ) :
return h , schemePSS , pssParamsOK ( params , newHash ( ) . Size ( ) , s . DigestAlg )
return h , schemePSS , pssParamsOK ( params , newHash ( ) . Size ( ) , s . DigestAlg )
}
}
return 0 , 0 , false
return 0 , 0 , false
@ -109,18 +112,17 @@ func pssParamsOK(params []byte, hashLen int, digest algID) bool {
switch e [ 0 ] {
switch e [ 0 ] {
case 0xa0 :
case 0xa0 :
a , err := parseAlgID ( in [ 0 ] )
a , err := parseAlgID ( in [ 0 ] )
hashOK = err == nil && a. OID . Equal ( digest . OID ) && ( a . Params == nil || bytes . Equal ( a . Params , [ ] byte { 5 , 0 } ) )
hashOK = err == nil && bytes. Equal ( a . OID , digest . OID ) && ( a . Params == nil || bytes . Equal ( a . Params , [ ] byte { 5 , 0 } ) )
case 0xa1 :
case 0xa1 :
a , err := parseAlgID ( in [ 0 ] )
a , err := parseAlgID ( in [ 0 ] )
if err != nil || ! a. OID . Equal ( oidMGF1 ) || a . Params == nil {
if err != nil || ! bytes. Equal ( a . OID , oidMGF1 ) || a . Params == nil {
return false
return false
}
}
inner , err := parseAlgID ( a . Params )
inner , err := parseAlgID ( a . Params )
mgfOK = err == nil && inner. OID . Equal ( digest . OID ) && ( inner . Params == nil || bytes . Equal ( inner . Params , [ ] byte { 5 , 0 } ) )
mgfOK = err == nil && bytes. Equal ( inner . OID , digest . OID ) && ( inner . Params == nil || bytes . Equal ( inner . Params , [ ] byte { 5 , 0 } ) )
case 0xa2 :
case 0xa2 :
var n int
n , ok := smallInt ( in [ 0 ] )
_ , err := asn1 . Unmarshal ( in [ 0 ] , & n )
saltOK = ok && n == hashLen
saltOK = err == nil && n == hashLen
default : // [3] trailerField is 1, its DEFAULT: DER does not write it
default : // [3] trailerField is 1, its DEFAULT: DER does not write it
return false
return false
}
}
@ -130,73 +132,124 @@ func pssParamsOK(params []byte, hashLen int, digest algID) bool {
return hashOK && mgfOK && saltOK
return hashOK && mgfOK && saltOK
}
}
// publicKey returns the key of the certificate when it is in the table:
// smallInt reads an INTEGER element of at most 4 bytes that is not negative.
// RSA of 2048 to 4096 bits with an odd exponent from 3 to 2^31 - 1, or ECDSA
func smallInt ( b [ ] byte ) ( int , bool ) {
// on P-256, P-384 or P-521.
if len ( b ) == 0 || b [ 0 ] != 0x02 {
return 0 , false
}
c , err := der . Content ( b )
if err != nil || len ( c ) == 0 || len ( c ) > 4 || c [ 0 ] & 0x80 != 0 {
return 0 , false
}
n := 0
for _ , x := range c {
n = n << 8 | int ( x )
}
return n , true
}
// publicKey returns the key of the certificate when the table has it (spec
// §29.10): a SubjectPublicKeyInfo of rsaEncryption with NULL parameters and
// an RSAPublicKey of exactly a modulus and an exponent, the modulus odd and
// of 2048 to 4096 bits and the exponent odd from 3 to 2^31 - 1; or of
// id-ecPublicKey with the named curve P-256, P-384 or P-521 and the
// uncompressed form of a point of it. Anything else is not usable.
func ( c * Cert ) publicKey ( ) ( any , scheme , bool ) {
func ( c * Cert ) publicKey ( ) ( any , scheme , bool ) {
k , err := x509 . ParsePKIXPublicKey ( c . SPKI )
_ , f , err := der . Split ( c . SPKI )
if err != nil || len ( f ) != 2 || f [ 0 ] [ 0 ] != 0x30 || f [ 1 ] [ 0 ] != 0x03 {
return nil , 0 , false
}
alg , err := parseAlgID ( f [ 0 ] )
if err != nil {
if err != nil {
return nil , 0 , false
return nil , 0 , false
}
}
switch k := k . ( type ) {
bits , err := der . Content ( f [ 1 ] )
case * rsa . PublicKey :
if err != nil || len ( bits ) < 2 || bits [ 0 ] != 0 {
bits := k . N . BitLen ( )
if bits < 2048 || bits > 4096 || k . E < 3 || k . E % 2 == 0 || int64 ( k . E ) > 1 << 31 - 1 {
return nil , 0 , false
return nil , 0 , false
}
}
return k , schemePKCS1 , true
key := bits [ 1 : ]
case * ecdsa . PublicKey :
switch {
switch k . Curve {
case bytes . Equal ( alg . OID , oidRSAEncryption ) && bytes . Equal ( alg . Params , [ ] byte { 5 , 0 } ) :
case elliptic . P256 ( ) , elliptic . P384 ( ) , elliptic . P521 ( ) :
if der . Check ( key ) != nil {
return k , schemeECDSA , true
return nil , 0 , fals e
}
}
id , ne , err := der . Split ( key )
if err != nil || id != 0x30 || len ( ne ) != 2 || ne [ 0 ] [ 0 ] != 0x02 || ne [ 1 ] [ 0 ] != 0x02 {
return nil , 0 , false
}
}
nb , _ := der . Content ( ne [ 0 ] )
eb , _ := der . Content ( ne [ 1 ] )
if nb [ 0 ] & 0x80 != 0 || eb [ 0 ] & 0x80 != 0 || len ( eb ) > 4 {
return nil , 0 , false
}
n := new ( big . Int ) . SetBytes ( nb )
e := new ( big . Int ) . SetBytes ( eb ) . Int64 ( )
if b := n . BitLen ( ) ; b < 2048 || b > 4096 || n . Bit ( 0 ) == 0 || e < 3 || e % 2 == 0 || e > 1 << 31 - 1 {
return nil , 0 , false
return nil , 0 , false
}
// algorithmsOK reports whether the algorithms of the SignerInfo and the key of
// its certificate are in the table of spec §29.10.
func ( s * SignerInfo ) algorithmsOK ( ) bool {
_ , sch , ok := s . params ( )
if ! ok {
return false
}
}
_ , ksch , ok := s . Cert . publicKey ( )
return & rsa . PublicKey { N : n , E : int ( e ) } , schemePKCS1 , true
case bytes . Equal ( alg . OID , oidECPublicKey ) :
curveOID , ok := oidOf ( alg . Params )
if ! ok {
if ! ok {
return false
return nil , 0 , false
}
var curve elliptic . Curve
switch {
case bytes . Equal ( curveOID , oidP256 ) :
curve = elliptic . P256 ( )
case bytes . Equal ( curveOID , oidP384 ) :
curve = elliptic . P384 ( )
case bytes . Equal ( curveOID , oidP521 ) :
curve = elliptic . P521 ( )
default :
return nil , 0 , false
}
k , err := ecdsa . ParseUncompressedPublicKey ( curve , key )
if err != nil {
return nil , 0 , false
}
}
return sch == ksch || sch == schemePSS && ksch == schemePKCS1
return k , schemeECDSA , true
}
return nil , 0 , false
}
}
// Check checks the signature of the SignerInfo over message, the bytes that
// Check checks the signature of the SignerInfo over message, the bytes that
// the signature is detached from (spec §29.10): not verifiable for an
// the signature is detached from (spec §29.10), in the order of the spec: not
// algorithm outside the table; invalid when the message-digest is not the
// verifiable for an algorithm, a key or a curve outside the table; invalid
// hash of message or the signature of the signedAttrs does not verify.
// when the message-digest is not the hash of message, or the signature of the
// signedAttrs does not verify with the key of the certificate, which is the
// case of a key of a scheme other than the one of the algorithm.
func ( s * SignerInfo ) Check ( message [ ] byte ) Result {
func ( s * SignerInfo ) Check ( message [ ] byte ) Result {
if ! s . algorithmsOK ( ) {
h , sch , ok := s . params ( )
if ! ok {
return NotVerifiable
}
key , ksch , ok := s . Cert . publicKey ( )
if ! ok {
return NotVerifiable
return NotVerifiable
}
}
h , sch , _ := s . params ( )
if sum := hashBytes ( h , message ) ; ! bytes . Equal ( sum , s . MessageDigest ) {
if sum := hashBytes ( h , message ) ; ! bytes . Equal ( sum , s . MessageDigest ) {
return Invalid
return Invalid
}
}
if sch != ksch && ! ( sch == schemePSS && ksch == schemePKCS1 ) {
return Invalid
}
// The signature covers the signedAttrs with the tag of a SET.
// The signature covers the signedAttrs with the tag of a SET.
attrs := bytes . Clone ( s . SignedAttrs )
attrs := bytes . Clone ( s . SignedAttrs )
attrs [ 0 ] = 0x31
attrs [ 0 ] = 0x31
digest := hashBytes ( h , attrs )
digest := hashBytes ( h , attrs )
key , _ , _ := s . Cert . publicKey ( )
var valid bool
var ok bool
switch k := key . ( type ) {
switch k := key . ( type ) {
case * rsa . PublicKey :
case * rsa . PublicKey :
if sch == schemePSS {
if sch == schemePSS {
ok = rsa . VerifyPSS ( k , h , digest , s . Signature , & rsa . PSSOptions { SaltLength : h . Size ( ) , Hash : h } ) == nil
valid = rsa . VerifyPSS ( k , h , digest , s . Signature , & rsa . PSSOptions { SaltLength : h . Size ( ) , Hash : h } ) == nil
} else {
} else {
ok = rsa . VerifyPKCS1v15 ( k , h , digest , s . Signature ) == nil
valid = rsa . VerifyPKCS1v15 ( k , h , digest , s . Signature ) == nil
}
}
case * ecdsa . PublicKey :
case * ecdsa . PublicKey :
ok = ecdsa . VerifyASN1 ( k , digest , s . Signature )
valid = ecdsa . VerifyASN1 ( k , digest , s . Signature )
}
}
if ! ok {
if ! valid {
return Invalid
return Invalid
}
}
return Valid
return Valid
@ -216,7 +269,7 @@ type Token struct {
GenTime time . Time
GenTime time . Time
Accuracy time . Duration
Accuracy time . Duration
// ImprintAlg is the hash of the messageImprint, and Imprint the hash.
// ImprintAlg is the hash of the messageImprint, and Imprint the hash.
ImprintAlg a sn1. ObjectIdentifier
ImprintAlg a lgID
Imprint [ ] byte
Imprint [ ] byte
// TSA is the certificate of the time-stamping authority.
// TSA is the certificate of the time-stamping authority.
TSA * Cert
TSA * Cert
@ -224,9 +277,9 @@ type Token struct {
data * SignedData
data * SignedData
}
}
// maxAccuracy bounds the seconds of accuracy : far above any real one, and far
// maxAccuracy bounds the seconds of accuracy (spec §29.11) : far above any
// below what would overflow a Duration.
// real one, and far below what would overflow a Duration.
const maxAccuracy = 1 << 31
const maxAccuracy = 1 << 31 - 1
// ParseToken reads a time-stamp token. It fails with ErrForm when the form
// ParseToken reads a time-stamp token. It fails with ErrForm when the form
// breaks the profile, and with ErrAlgorithm when an algorithm is outside the
// breaks the profile, and with ErrAlgorithm when an algorithm is outside the
@ -237,23 +290,23 @@ func ParseToken(b []byte) (*Token, error) {
return nil , err
return nil , err
}
}
// The TSTInfo is an OCTET STRING inside the token, so the check of the
// The TSTInfo is an OCTET STRING inside the token, so the check of the
// token did not reach it, and encoding/asn1 would let through what DER
// token did not reach it: it is read here, field by field.
// forbids: it is read here, field by field.
t , imprintAlg , hash , err := parseTSTInfo ( sd . EContent )
t , imprintAlg , hash , err := parseTSTInfo ( sd . EContent )
if err != nil {
if err != nil {
return nil , err
return nil , err
}
}
t . TSA , t . data = sd . Signers [ 0 ] . Cert , sd
t . TSA , t . data = sd . Signers [ 0 ] . Cert , sd
ia , err := parseAlgID ( imprintAlg )
if t . ImprintAlg , err = parseAlgID ( imprintAlg ) ; err != nil {
if err != nil {
return nil , err
return nil , err
}
}
t . ImprintAlg , t . Imprint = ia . OID , hash
t . Imprint = hash
newHash , ok := ia . hashOf ( )
if _ , ok := t . ImprintAlg . hashOf ( ) ; ! ok {
if ok && len ( hash ) != newHash ( ) . Size ( ) {
return nil , ErrAlgorithm
return nil , formErr ( "a messageImprint of the wrong length" )
}
if _ , _ , ok := sd . Signers [ 0 ] . params ( ) ; ! ok {
return nil , ErrAlgorithm
}
}
if ! ok || ! sd . Signers [ 0 ] . algorithmsOK ( ) {
if _ , _ , ok := t . TSA . publicKey ( ) ; ! ok {
return nil , ErrAlgorithm
return nil , ErrAlgorithm
}
}
return t , nil
return t , nil
@ -273,11 +326,7 @@ func parseTSTInfo(b []byte) (*Token, []byte, []byte, error) {
if err != nil || id != 0x30 || len ( f ) < 5 {
if err != nil || id != 0x30 || len ( f ) < 5 {
return bad ( "not a SEQUENCE of at least five fields" )
return bad ( "not a SEQUENCE of at least five fields" )
}
}
var version int
if v , ok := smallInt ( f [ 0 ] ) ; ! ok || v != 1 {
if f [ 0 ] [ 0 ] != 0x02 {
return bad ( "the version" )
}
if _ , err := asn1 . Unmarshal ( f [ 0 ] , & version ) ; err != nil || version != 1 {
return bad ( "the version is not 1" )
return bad ( "the version is not 1" )
}
}
if f [ 1 ] [ 0 ] != 0x06 || f [ 3 ] [ 0 ] != 0x02 || f [ 4 ] [ 0 ] != 0x18 {
if f [ 1 ] [ 0 ] != 0x06 || f [ 3 ] [ 0 ] != 0x02 || f [ 4 ] [ 0 ] != 0x18 {
@ -291,9 +340,9 @@ func parseTSTInfo(b []byte) (*Token, []byte, []byte, error) {
if err != nil {
if err != nil {
return bad ( "the messageImprint" )
return bad ( "the messageImprint" )
}
}
gen , err := parseGen Time( f [ 4 ] )
gen , _, err := der . Parse Time( f [ 4 ] )
if err != nil {
if err != nil {
return bad ( err . Error ( ) )
return bad ( "genTime: " + err . Error ( ) )
}
}
t := & Token { GenTime : gen }
t := & Token { GenTime : gen }
rest := f [ 5 : ]
rest := f [ 5 : ]
@ -324,47 +373,10 @@ func parseTSTInfo(b []byte) (*Token, []byte, []byte, error) {
return t , mi [ 0 ] , hash , nil
return t , mi [ 0 ] , hash , nil
}
}
// parseGenTime reads a GeneralizedTime as RFC 3161 and DER write it:
// parseAccuracy reads Accuracy: seconds from 0 to 2^31 - 1, and millis and
// YYYYMMDDHHMMSS, a fraction without a trailing zero, and Z.
// micros from 1 to 999, in that order, each optional (RFC 3161 2.4.2, spec
func parseGenTime ( b [ ] byte ) ( time . Time , error ) {
// §29.11), each a minimal INTEGER. A negative number would make a seal after
c , err := der . Content ( b )
// the opening date look before it.
if err != nil {
return time . Time { } , errors . New ( "genTime" )
}
s := string ( c )
if len ( s ) < 15 || s [ len ( s ) - 1 ] != 'Z' {
return time . Time { } , errors . New ( "genTime is not in UTC with the letter Z" )
}
body := s [ : len ( s ) - 1 ]
t , err := time . Parse ( "20060102150405" , body [ : 14 ] )
if err != nil {
return time . Time { } , errors . New ( "genTime does not parse" )
}
if frac := body [ 14 : ] ; frac != "" {
if len ( frac ) < 2 || frac [ 0 ] != '.' || frac [ len ( frac ) - 1 ] == '0' {
return time . Time { } , errors . New ( "genTime has a fraction that DER does not write" )
}
var nanos int
digits := frac [ 1 : ]
for i := 0 ; i < len ( digits ) ; i ++ {
if digits [ i ] < '0' || digits [ i ] > '9' {
return time . Time { } , errors . New ( "genTime has a fraction that is not digits" )
}
}
for i := 0 ; i < 9 ; i ++ {
nanos *= 10
if i < len ( digits ) {
nanos += int ( digits [ i ] - '0' )
}
}
t = t . Add ( time . Duration ( nanos ) )
}
return t , nil
}
// parseAccuracy reads Accuracy: seconds from 0, and millis and micros from 1
// to 999, in that order, each optional (RFC 3161 2.4.2). A negative number
// would make a seal after the opening date look before it.
func parseAccuracy ( b [ ] byte ) ( time . Duration , error ) {
func parseAccuracy ( b [ ] byte ) ( time . Duration , error ) {
_ , f , err := der . Split ( b )
_ , f , err := der . Split ( b )
if err != nil {
if err != nil {
@ -372,9 +384,9 @@ func parseAccuracy(b []byte) (time.Duration, error) {
}
}
var total time . Duration
var total time . Duration
if len ( f ) > 0 && f [ 0 ] [ 0 ] == 0x02 {
if len ( f ) > 0 && f [ 0 ] [ 0 ] == 0x02 {
var secs int64
secs , ok := smallInt ( f [ 0 ] )
if _ , err := asn1 . Unmarshal ( f [ 0 ] , & secs ) ; err != nil || secs < 0 || secs > maxAccuracy {
if ! ok || secs > maxAccuracy {
return 0 , errors . New ( "accuracy seconds outside 0 to 2^31 ")
return 0 , errors . New ( "accuracy seconds outside 0 to 2^31 - 1 ")
}
}
total += time . Duration ( secs ) * time . Second
total += time . Duration ( secs ) * time . Second
f = f [ 1 : ]
f = f [ 1 : ]
@ -385,8 +397,8 @@ func parseAccuracy(b []byte) (time.Duration, error) {
} { { 0x80 , time . Millisecond } , { 0x81 , time . Microsecond } } {
} { { 0x80 , time . Millisecond } , { 0x81 , time . Microsecond } } {
if len ( f ) > 0 && f [ 0 ] [ 0 ] == part . tag {
if len ( f ) > 0 && f [ 0 ] [ 0 ] == part . tag {
c , err := der . Content ( f [ 0 ] )
c , err := der . Content ( f [ 0 ] )
if err != nil || len ( c ) < 1 || len ( c ) > 2 || c [ 0 ] & 0x80 != 0 {
if err != nil || len ( c ) < 1 || len ( c ) > 2 || c [ 0 ] & 0x80 != 0 || len ( c ) == 2 && c [ 0 ] == 0 && c [ 1 ] & 0x80 == 0 {
return 0 , errors . New ( "accuracy millis or micros ")
return 0 , errors . New ( "accuracy millis or micros that are not a minimal INTEGER ")
}
}
n := 0
n := 0
for _ , x := range c {
for _ , x := range c {
@ -407,18 +419,19 @@ func parseAccuracy(b []byte) (time.Duration, error) {
// ImprintIsSHA256 reports whether the messageImprint uses SHA-256, which a
// ImprintIsSHA256 reports whether the messageImprint uses SHA-256, which a
// seal of seal_type 2 requires (spec §29.11).
// seal of seal_type 2 requires (spec §29.11).
func ( t * Token ) ImprintIsSHA256 ( ) bool { return t. ImprintAlg . Equal ( oidSHA256 ) }
func ( t * Token ) ImprintIsSHA256 ( ) bool { return bytes. Equal ( t . ImprintAlg . OID , oidSHA256 ) }
// Check verifies the token over subject, the bytes that it seals: the
// Check verifies the token over subject, the bytes that it seals: the
// message-digest is the hash of the TSTInfo, the signature of the TSA
// message-digest is the hash of the TSTInfo, the signature of the TSA
// verifies, the messageImprint is the hash of subject and the certificate of
// verifies, the messageImprint is the hash of subject, of any length, and the
// the TSA is valid at genTime. It returns false for the verdict S3.
// certificate of the TSA is valid at genTime. It returns false for the
// verdict S3.
func ( t * Token ) Check ( subject [ ] byte ) bool {
func ( t * Token ) Check ( subject [ ] byte ) bool {
s := t . data . Signers [ 0 ]
s := t . data . Signers [ 0 ]
if s . Check ( t . data . EContent ) != Valid {
if s . Check ( t . data . EContent ) != Valid {
return false
return false
}
}
newHash , _ := algID{ OID : t. ImprintAlg } . hashOf ( )
newHash , _ := t. ImprintAlg . hashOf ( )
h := newHash ( )
h := newHash ( )
h . Write ( subject )
h . Write ( subject )
return bytes . Equal ( h . Sum ( nil ) , t . Imprint ) && t . TSA . ValidAt ( t . GenTime )
return bytes . Equal ( h . Sum ( nil ) , t . Imprint ) && t . TSA . ValidAt ( t . GenTime )