@@ -8,8 +8,7 @@ import Crypto
88import  AsyncHTTPClient
99import  NIOFoundationCompat
1010
11- class  ChainVerifier  { 
12-     
11+ actor  ChainVerifier  { 
1312    private  static  let  EXPECTED_CHAIN_LENGTH   =  3 
1413    private  static  let  EXPECTED_JWT_SEGMENTS   =  3 
1514    private  static  let  EXPECTED_ALGORITHM   =  " ES256 " 
@@ -28,7 +27,7 @@ class ChainVerifier {
2827        self . verifiedPublicKeyCache =  [ : ] 
2928    } 
3029
31-     func  verify< T:  DecodedSignedData > ( signedData:  String ,  type:  T . Type ,  onlineVerification:  Bool ,  environment:  AppStoreEnvironment )  async  ->  VerificationResult < T >  where  T:  Decodable  { 
30+     func  verify< T:  DecodedSignedData > ( signedData:  String ,  type:  T . Type ,  onlineVerification:  Bool ,  environment:  AppStoreEnvironment ,  currentTime :   Date   =   . now )  async  ->  VerificationResult < T >  where  T:  Decodable   &   Sendable  { 
3231        let  header :  JWTHeader 
3332        let  decodedBody :  T 
3433        do  { 
@@ -67,9 +66,9 @@ class ChainVerifier {
6766        do  { 
6867            let  leafCertificate  =  try   Certificate ( derEncoded:  Array ( leaf_der_enocded) ) 
6968            let  intermediateCertificate  =  try   Certificate ( derEncoded:  Array ( intermeidate_der_encoded) ) 
70-             let  validationTime  =  !onlineVerification && decodedBody. signedDateOptional !=  nil  ?  decodedBody. signedDateOptional! :  getDate ( ) 
69+             let  validationTime  =  !onlineVerification && decodedBody. signedDateOptional !=  nil  ?  decodedBody. signedDateOptional! :  currentTime 
7170
72-             let  verificationResult  =  await  verifyChain ( leaf:  leafCertificate,  intermediate:  intermediateCertificate,  online:  onlineVerification,  validationTime:  validationTime) 
71+             let  verificationResult  =  await  verifyChain ( leaf:  leafCertificate,  intermediate:  intermediateCertificate,  online:  onlineVerification,  validationTime:  validationTime,  currentTime :  currentTime ) 
7372            switch  verificationResult { 
7473            case  . validCertificate( let  chain) : 
7574                let  leafCertificate  =  chain. first!
@@ -90,22 +89,22 @@ class ChainVerifier {
9089        } 
9190    } 
9291
93-     func  verifyChain( leaf:  Certificate ,  intermediate:  Certificate ,  online:  Bool ,  validationTime:  Date )  async  ->  X509 . VerificationResult  { 
92+     func  verifyChain( leaf:  Certificate ,  intermediate:  Certificate ,  online:  Bool ,  validationTime:  Date ,  currentTime :   Date   =   . now )  async  ->  X509 . VerificationResult  { 
9493        if  online { 
9594            if  let  cachedResult =  verifiedPublicKeyCache [ CacheKey ( leaf:  leaf,  intermediate:  intermediate) ]  { 
96-                 if  cachedResult. expirationTime >  getDate ( )  { 
95+                 if  cachedResult. expirationTime >  currentTime  { 
9796                    return  cachedResult. publicKey
9897                } 
9998            } 
10099        } 
101-         let  verificationResult  =  await  verifyChainWithoutCaching ( leaf:  leaf,  intermediate:  intermediate,  online:  online,  validationTime:  validationTime) 
100+         let  verificationResult  =  await  verifyChainWithoutCaching ( leaf:  leaf,  intermediate:  intermediate,  online:  online,  validationTime:  validationTime,  currentTime :  currentTime ) 
102101
103102        if  online { 
104103            if  case . validCertificate =  verificationResult { 
105-                 verifiedPublicKeyCache [ CacheKey ( leaf:  leaf,  intermediate:  intermediate) ]  =  CacheValue ( expirationTime:  getDate ( ) . addingTimeInterval ( TimeInterval ( integerLiteral:  ChainVerifier . CACHE_TIME_LIMIT) ) ,  publicKey:  verificationResult) 
104+                 verifiedPublicKeyCache [ CacheKey ( leaf:  leaf,  intermediate:  intermediate) ]  =  CacheValue ( expirationTime:  currentTime . addingTimeInterval ( TimeInterval ( integerLiteral:  ChainVerifier . CACHE_TIME_LIMIT) ) ,  publicKey:  verificationResult) 
106105                if  verifiedPublicKeyCache. count >  ChainVerifier . MAXIMUM_CACHE_SIZE { 
107106                    for  kv  in  verifiedPublicKeyCache { 
108-                         if  kv. value. expirationTime <  getDate ( )  { 
107+                         if  kv. value. expirationTime <  currentTime  { 
109108                            verifiedPublicKeyCache. removeValue ( forKey:  kv. key) 
110109                        } 
111110                    } 
@@ -116,21 +115,17 @@ class ChainVerifier {
116115        return  verificationResult
117116    } 
118117
119-     func  verifyChainWithoutCaching( leaf:  Certificate ,  intermediate:  Certificate ,  online:  Bool ,  validationTime:  Date )  async  ->  X509 . VerificationResult  { 
118+     nonisolated   func  verifyChainWithoutCaching( leaf:  Certificate ,  intermediate:  Certificate ,  online:  Bool ,  validationTime:  Date ,  currentTime :   Date   =   . now )  async  ->  X509 . VerificationResult  { 
120119        var  verifier  =  Verifier ( rootCertificates:  self . store)  { 
121120            RFC5280Policy ( validationTime:  validationTime) 
122121            AppStoreOIDPolicy ( ) 
123122            if  online { 
124-                 OCSPVerifierPolicy ( failureMode:  . hard,  requester:  requester,  validationTime:  getDate ( ) ) 
123+                 OCSPVerifierPolicy ( failureMode:  . hard,  requester:  requester,  validationTime:  currentTime ) 
125124            } 
126125        } 
127126        let  intermediateStore  =  CertificateStore ( [ intermediate] ) 
128127        return  await  verifier. validate ( leafCertificate:  leaf,  intermediates:  intermediateStore) 
129128    } 
130-     
131-     func  getDate( )  ->  Date  { 
132-         return  Date ( ) 
133-     } 
134129} 
135130
136131struct  CacheKey :  Hashable  { 
@@ -217,7 +212,7 @@ final class Requester: OCSPRequester {
217212    private  struct  OCSPFetchError :  Error  { } 
218213} 
219214
220- public  enum  VerificationResult < T>  { 
215+ public  enum  VerificationResult < T:   Hashable   &   Sendable > :   Hashable ,   Sendable  { 
221216    case  valid( T ) 
222217    case  invalid( VerificationError ) 
223218} 
0 commit comments