├── p12checker.h ├── README.md └── p12checker.cpp /p12checker.h: -------------------------------------------------------------------------------- 1 | // 2 | // p12checker.hpp 3 | // ECSignerForiOS 4 | // 5 | // Created by Even on 2020/9/12. 6 | // Copyright © 2020 even_cheng. All rights reserved. 7 | // 8 | #include 9 | 10 | bool isP12Revoked(X509 * x509, bool g3); 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # p12Checker 2 | 提取p12内容,检查p12状态 3 | 4 | 改接口只是检查P12状态,获取P12内容逻辑如下: 5 | ``` 6 | 导入头文件 7 | #include "pkcs12.h" 8 | #include "p12checker.h" 9 | ``` 10 | 11 | ``` 12 | - (void)readP12:(NSString *)p12_path pwd:(NSString *)pwd { 13 | 14 | PKCS12 *p12 = NULL; 15 | X509* usrCert = NULL; 16 | EVP_PKEY* pkey = NULL; 17 | STACK_OF(X509)* ca = NULL; 18 | char* password = (char*)[pwd cStringUsingEncoding:NSUTF8StringEncoding]; 19 | 20 | BIO*bio = NULL; 21 | char* p = NULL; 22 | 23 | bio = BIO_new_file([p12_path UTF8String], "r"); 24 | p12 = d2i_PKCS12_bio(bio, NULL); //得到p12结构 25 | BIO_free_all(bio); 26 | PKCS12_parse(p12, password, &pkey, &usrCert, &ca); //得到x509结构 27 | if (usrCert) 28 | { 29 | fprintf(stdout, "Subject:"); 30 | p = X509_NAME_oneline(X509_get_subject_name(usrCert), NULL, 0); 31 | 32 | //读取证书内容 33 | NSDictionary* subject = [self readSubjectFormX509:p]; 34 | NSString* country = subject[@"U"]; 35 | NSString* name = subject[@"CN"]; 36 | NSString* organization = subject[@"O"]; 37 | NSString* organization_unit = subject[@"OU"]; 38 | NSString* user_ID = subject[@"UID"]; 39 | NSString* country = subject[@"C"]; 40 | 41 | 42 | ASN1_TIME* before = X509_get_notBefore(usrCert); 43 | long start_time = [self readRealTimeForX509:(char *)before->data]; 44 | 45 | ASN1_TIME* after = X509_get_notAfter(usrCert); 46 | long expire_time = [self readRealTimeForX509:(char *)after->data]; 47 | 48 | dispatch_async(dispatch_get_global_queue(0, 0), ^{ 49 | //9月之后苹果新增G3类型的根证书,这里需要区分 50 | bool g3 = [self isG3ForX509:usrCert]; 51 | bool revoked = isP12Revoked(usrCert, g3); 52 | }); 53 | } 54 | ``` 55 | 56 | ``` 57 | - (long )readRealTimeForX509:(char *)x509data{ 58 | 59 | NSString* x509TimeString = [NSString stringWithUTF8String:x509data]; 60 | if (x509TimeString.length<12) { 61 | return 0; 62 | } 63 | NSString* start_time = [NSString stringWithFormat:@"20%@-%@-%@ %@:%@:%@",[x509TimeString substringWithRange:NSMakeRange(0, 2)], [x509TimeString substringWithRange:NSMakeRange(2, 2)], [x509TimeString substringWithRange:NSMakeRange(4, 2)], [x509TimeString substringWithRange:NSMakeRange(6, 2)], [x509TimeString substringWithRange:NSMakeRange(8, 2)], [x509TimeString substringWithRange:NSMakeRange(10, 2)]]; 64 | long timeLong = [NSDate getDateLongWithDateStr:start_time]; 65 | return timeLong+8*60*60; 66 | } 67 | ``` 68 | 69 | ``` 70 | - (NSDictionary *)readSubjectFormX509:(char *)x509data{ 71 | 72 | NSMutableDictionary* mdic = [NSMutableDictionary dictionary]; 73 | NSString* x509String = [NSString stringWithUTF8String:x509data]; 74 | NSArray* objs = [x509String componentsSeparatedByString:@"/"]; 75 | for (NSString* obj in objs) { 76 | NSArray* content = [obj componentsSeparatedByString:@"="]; 77 | if (content.count == 2) { 78 | NSDictionary* dic = @{content.firstObject:content.lastObject}; 79 | [mdic addEntriesFromDictionary:dic]; 80 | } 81 | } 82 | return mdic.copy; 83 | } 84 | ``` 85 | 86 | ``` 87 | - (bool)isG3ForX509:(X509*)usrCert{ 88 | 89 | X509_NAME* name = X509_get_issuer_name(usrCert); 90 | const unsigned char* der = NULL; 91 | size_t leng; 92 | X509_NAME_get0_der(name, &der, &leng); 93 | const X509_NAME_ENTRY *ne = X509_NAME_get_entry(name, 2); 94 | ASN1_OBJECT *obj = X509_NAME_ENTRY_get_object(ne); 95 | ASN1_STRING *asn1_data = X509_NAME_ENTRY_get_data(ne); 96 | bool g3 = strcmp((char *)asn1_data->data, "G3") == 0; //Apple Worldwide Developer Relations 97 | 98 | return g3; 99 | } 100 | ``` 101 | 博客地址: 102 | https://www.jianshu.com/p/31987f448e5f 103 | -------------------------------------------------------------------------------- /p12checker.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // p12checker.cpp 3 | // ECSignerForiOS 4 | // 5 | // Created by Even on 2020/9/12. 6 | // Copyright © 2020 even_cheng. All rights reserved. 7 | // 8 | 9 | #include "p12checker.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "ocsp.h" 22 | #include //for select 23 | #include "asn1t.h" 24 | #include "ossl_typ.h" 25 | #include 26 | 27 | using std::cout; 28 | using std::endl; 29 | using std::stringstream; 30 | using std::map; 31 | using std::vector; 32 | using std::string; 33 | 34 | //---------------------------------------------------------------------- 35 | vector ocsp_urls(X509 *x509) 36 | { 37 | vector list; 38 | STACK_OF(OPENSSL_STRING) *ocsp_list = X509_get1_ocsp(x509); 39 | for (int j = 0; j < sk_OPENSSL_STRING_num(ocsp_list); j++) 40 | { 41 | list.push_back( string( sk_OPENSSL_STRING_value(ocsp_list, j) ) ); 42 | } 43 | X509_email_free(ocsp_list); 44 | return list; 45 | } 46 | //---------------------------------------------------------------------- 47 | int prepareRequest(OCSP_REQUEST **req, X509 *cert, const EVP_MD *cert_id_md,X509 *issuer, 48 | STACK_OF(OCSP_CERTID) *ids) 49 | { 50 | OCSP_CERTID *id; 51 | if(!issuer) 52 | { 53 | std::cerr << "No issuer certificate specified" << endl; 54 | //BIO_printf(bio_err, "No issuer certificate specified\n"); 55 | return 0; 56 | } 57 | if(!*req) *req = OCSP_REQUEST_new(); 58 | if(!*req) goto err; 59 | id = OCSP_cert_to_id(cert_id_md, cert, issuer); 60 | if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err; 61 | if(!OCSP_request_add0_id(*req, id)) goto err; 62 | return 1; 63 | 64 | err: 65 | std::cerr << "Error Creating OCSP request" << endl; 66 | //BIO_printf(bio_err, "Error Creating OCSP request\n"); 67 | return 0; 68 | } 69 | //---------------------------------------------------------------------- 70 | OCSP_RESPONSE * queryResponder(BIO *err, BIO *cbio, char *path, 71 | char *host, OCSP_REQUEST *req, int req_timeout) 72 | { 73 | int fd; 74 | int rv; 75 | int i; 76 | OCSP_REQ_CTX *ctx = NULL; 77 | OCSP_RESPONSE *rsp = NULL; 78 | fd_set confds; 79 | struct timeval tv; 80 | 81 | if (req_timeout != -1) 82 | BIO_set_nbio(cbio, 1); 83 | 84 | rv = BIO_do_connect(cbio); 85 | 86 | if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio))) 87 | { 88 | std::cerr << "Error connecting BIO" << endl; 89 | return NULL; 90 | } 91 | 92 | if (BIO_get_fd(cbio, &fd) <= 0) 93 | { 94 | std::cerr << "Can't get connection fd" << endl; 95 | goto err; 96 | } 97 | 98 | if (req_timeout != -1 && rv <= 0) 99 | { 100 | FD_ZERO(&confds); 101 | FD_SET(fd, &confds); 102 | tv.tv_usec = 0; 103 | tv.tv_sec = req_timeout; 104 | rv = select(fd + 1, NULL, &confds, NULL, &tv); 105 | if (rv == 0) 106 | { 107 | std::cerr << "Timeout on connect" << endl; 108 | //BIO_puts(err, "Timeout on connect\n"); 109 | return NULL; 110 | } 111 | } 112 | 113 | ctx = OCSP_sendreq_new(cbio, path, NULL, -1); 114 | if (!ctx) 115 | return NULL; 116 | 117 | if (!OCSP_REQ_CTX_add1_header(ctx, "Host", host)) 118 | goto err; 119 | 120 | if (!OCSP_REQ_CTX_set1_req(ctx, req)) 121 | goto err; 122 | 123 | for (;;) 124 | { 125 | rv = OCSP_sendreq_nbio(&rsp, ctx); 126 | if (rv != -1) 127 | break; 128 | if (req_timeout == -1) 129 | continue; 130 | FD_ZERO(&confds); 131 | FD_SET(fd, &confds); 132 | tv.tv_usec = 0; 133 | tv.tv_sec = req_timeout; 134 | if (BIO_should_read(cbio)) 135 | rv = select(fd + 1, &confds, NULL, NULL, &tv); 136 | else if (BIO_should_write(cbio)) 137 | rv = select(fd + 1, NULL, &confds, NULL, &tv); 138 | else 139 | { 140 | std::cerr << "Unexpected retry condition" << endl; 141 | goto err; 142 | } 143 | if (rv == 0) 144 | { 145 | std::cerr << "Timeout on request" << endl; 146 | break; 147 | } 148 | if (rv == -1) 149 | { 150 | std::cerr << "Select error" << endl; 151 | break; 152 | } 153 | 154 | } 155 | err: 156 | if (ctx) 157 | OCSP_REQ_CTX_free(ctx); 158 | 159 | return rsp; 160 | } 161 | //---------------------------------------------------------------------- 162 | OCSP_RESPONSE * sendRequest(BIO *err, OCSP_REQUEST *req, 163 | char *host, char *path, char *port, int use_ssl, 164 | int req_timeout) 165 | { 166 | BIO *cbio = NULL; 167 | OCSP_RESPONSE *resp = NULL; 168 | cbio = BIO_new_connect(host); 169 | if (cbio && port && use_ssl==0) 170 | { 171 | BIO_set_conn_port(cbio, port); 172 | resp = queryResponder(err, cbio, path, host, req, req_timeout); 173 | if (!resp) 174 | std::cerr << "Error querying OCSP responder" << endl; 175 | } 176 | if (cbio) 177 | BIO_free_all(cbio); 178 | return resp; 179 | } 180 | 181 | 182 | int parseResponse(OCSP_RESPONSE *resp) 183 | { 184 | int is_revoked = 0; 185 | OCSP_BASICRESP *br = OCSP_response_get1_basic(resp); 186 | 187 | OCSP_SINGLERESP* single = OCSP_resp_get0(br, 0); 188 | OCSP_CERTSTATUS *cst = single->certStatus; 189 | if (cst->type == V_OCSP_CERTSTATUS_REVOKED) 190 | { 191 | is_revoked = -1; 192 | } 193 | 194 | OCSP_BASICRESP_free(br); 195 | return is_revoked; 196 | } 197 | 198 | //---------------------------------------------------------------------- 199 | int checkCertOCSP(X509 *x509, X509 *issuer) 200 | { 201 | int is_revoked=-1; 202 | 203 | BIO *bio_out = BIO_new_fp(stdout, BIO_NOCLOSE|BIO_FP_TEXT); 204 | BIO *bio_err = BIO_new_fp(stderr, BIO_NOCLOSE|BIO_FP_TEXT); 205 | 206 | if (issuer) 207 | { 208 | //build ocsp request 209 | OCSP_REQUEST *req = NULL; 210 | // STACK_OF(CONF_VALUE) *headers = NULL; 211 | STACK_OF(OCSP_CERTID) *ids = sk_OCSP_CERTID_new_null(); 212 | const EVP_MD *cert_id_md = EVP_sha1(); 213 | prepareRequest(&req, x509, cert_id_md, issuer, ids); 214 | 215 | //loop through OCSP urls 216 | STACK_OF(OPENSSL_STRING) *ocsp_list = X509_get1_ocsp(x509); 217 | for (int j = 0; j < sk_OPENSSL_STRING_num(ocsp_list) && is_revoked==-1; j++) 218 | { 219 | char *host = NULL, *port = NULL, *path = NULL; 220 | int use_ssl, req_timeout = 30; 221 | string ocsp_url0 = string( sk_OPENSSL_STRING_value(ocsp_list, j) ); 222 | 223 | char *ocsp_url = sk_OPENSSL_STRING_value(ocsp_list, j); 224 | if (OCSP_parse_url(ocsp_url, &host, &port, &path, &use_ssl) && !use_ssl) 225 | { 226 | //send ocsp request 227 | OCSP_RESPONSE *resp = sendRequest(bio_err, req, host, path, port, use_ssl, req_timeout); 228 | if (resp) 229 | { 230 | //see crypto/ocsp/ocsp_prn.c for examples parsing OCSP responses 231 | int responder_status = OCSP_response_status(resp); 232 | 233 | //parse response 234 | if (resp && responder_status == OCSP_RESPONSE_STATUS_SUCCESSFUL) 235 | { 236 | // OCSP_RESPONSE_print(bio_out, resp, 0); 237 | is_revoked = parseResponse(resp); 238 | } 239 | OCSP_RESPONSE_free(resp); 240 | } 241 | } 242 | OPENSSL_free(host); 243 | OPENSSL_free(path); 244 | OPENSSL_free(port); 245 | } 246 | X509_email_free(ocsp_list); 247 | OCSP_REQUEST_free(req); 248 | } 249 | 250 | BIO_free(bio_out); 251 | BIO_free(bio_err); 252 | return is_revoked; 253 | } 254 | //---------------------------------------------------------------------- 255 | string commonName(X509 *x509) 256 | { 257 | X509_NAME *subject = X509_get_subject_name(x509); 258 | int subject_position = X509_NAME_get_index_by_NID(subject, NID_commonName, 0); 259 | X509_NAME_ENTRY *entry = subject_position==-1 ? NULL : X509_NAME_get_entry(subject, subject_position); 260 | ASN1_STRING *d = X509_NAME_ENTRY_get_data(entry); 261 | return string( (char*)d->data, ASN1_STRING_length(d) ); 262 | } 263 | //---------------------------------------------------------------------- 264 | int isRevokedByOCSP(X509 * x509, const char issuer_bytes[]) 265 | { 266 | BIO *bio_mem2 = BIO_new(BIO_s_mem()); 267 | BIO_puts(bio_mem2, issuer_bytes); 268 | X509 * issuer = PEM_read_bio_X509(bio_mem2, NULL, NULL, NULL); 269 | int status = checkCertOCSP(x509, issuer); 270 | cout << commonName(x509) << " certificate, "; 271 | cout << "isRevokedByOCSP: " << status << endl; 272 | BIO_free(bio_mem2); 273 | X509_free(issuer); 274 | 275 | return status; 276 | } 277 | //---------------------------------------------------------------------- 278 | 279 | 280 | bool isP12Revoked(X509 * x509, bool g3) { 281 | 282 | OpenSSL_add_all_algorithms(); 283 | 284 | //苹果根证书 https://developer.apple.com/certificationauthority/AppleWWDRCA.cer 285 | const char issuer1_bytes[] = "-----BEGIN CERTIFICATE-----" "\n" 286 | "MIIEIjCCAwqgAwIBAgIIAd68xDltoBAwDQYJKoZIhvcNAQEFBQAwYjELMAkGA1UE" "\n" 287 | "BhMCVVMxEzARBgNVBAoTCkFwcGxlIEluYy4xJjAkBgNVBAsTHUFwcGxlIENlcnRp" "\n" 288 | "ZmljYXRpb24gQXV0aG9yaXR5MRYwFAYDVQQDEw1BcHBsZSBSb290IENBMB4XDTEz" "\n" 289 | "MDIwNzIxNDg0N1oXDTIzMDIwNzIxNDg0N1owgZYxCzAJBgNVBAYTAlVTMRMwEQYD" "\n" 290 | "VQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3JsZHdpZGUgRGV2ZWxv" "\n" 291 | "cGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3aWRlIERldmVsb3Bl" "\n" 292 | "ciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3" "\n" 293 | "DQEBAQUAA4IBDwAwggEKAoIBAQDKOFSmy1aqyCQ5SOmM7uxfuH8mkbw0U3rOfGOA" "\n" 294 | "YXdkXqUHI7Y5/lAtFVZYcC1+xG7BSoU+L/DehBqhV8mvexj/avoVEkkVCBmsqtsq" "\n" 295 | "Mu2WY2hSFT2Miuy/axiV4AOsAX2XBWfODoWVN2rtCbauZ81RZJ/GXNG8V25nNYB2" "\n" 296 | "NqSHgW44j9grFU57Jdhav06DwY3Sk9UacbVgnJ0zTlX5ElgMhrgWDcHld0WNUEi6" "\n" 297 | "Ky3klIXh6MSdxmilsKP8Z35wugJZS3dCkTm59c3hTO/AO0iMpuUhXf1qarunFjVg" "\n" 298 | "0uat80YpyejDi+l5wGphZxWy8P3laLxiX27Pmd3vG2P+kmWrAgMBAAGjgaYwgaMw" "\n" 299 | "HQYDVR0OBBYEFIgnFwmpthhgi+zruvZHWcVSVKO3MA8GA1UdEwEB/wQFMAMBAf8w" "\n" 300 | "HwYDVR0jBBgwFoAUK9BpR5R2Cf70a40uQKb3R01/CF4wLgYDVR0fBCcwJTAjoCGg" "\n" 301 | "H4YdaHR0cDovL2NybC5hcHBsZS5jb20vcm9vdC5jcmwwDgYDVR0PAQH/BAQDAgGG" "\n" 302 | "MBAGCiqGSIb3Y2QGAgEEAgUAMA0GCSqGSIb3DQEBBQUAA4IBAQBPz+9Zviz1smwv" "\n" 303 | "j+4ThzLoBTWobot9yWkMudkXvHcs1Gfi/ZptOllc34MBvbKuKmFysa/Nw0Uwj6OD" "\n" 304 | "Dc4dR7Txk4qjdJukw5hyhzs+r0ULklS5MruQGFNrCk4QttkdUGwhgAqJTleMa1s8" "\n" 305 | "Pab93vcNIx0LSiaHP7qRkkykGRIZbVf1eliHe2iK5IaMSuviSRSqpd1VAKmuu0sw" "\n" 306 | "ruGgsbwpgOYJd+W+NKIByn/c4grmO7i77LpilfMFY0GCzQ87HUyVpNur+cmV6U/k" "\n" 307 | "TecmmYHpvPm0KdIBembhLoz2IYrF+Hjhga6/05Cdqa3zr/04GpZnMBxRpVzscYqC" "\n" 308 | "tGwPDBUf" "\n" 309 | "-----END CERTIFICATE-----" "\n"; 310 | 311 | const char g3_issuer1_bytes[] = "-----BEGIN CERTIFICATE-----" "\n" 312 | "MIIEUTCCAzmgAwIBAgIQfK9pCiW3Of57m0R6wXjF7jANBgkqhkiG9w0BAQsFADBi" "\n" 313 | "MQswCQYDVQQGEwJVUzETMBEGA1UEChMKQXBwbGUgSW5jLjEmMCQGA1UECxMdQXBw" "\n" 314 | "bGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNVBAMTDUFwcGxlIFJvb3Qg" "\n" 315 | "Q0EwHhcNMjAwMjE5MTgxMzQ3WhcNMzAwMjIwMDAwMDAwWjB1MUQwQgYDVQQDDDtB" "\n" 316 | "cHBsZSBXb3JsZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9ucyBDZXJ0aWZpY2F0aW9u" "\n" 317 | "IEF1dGhvcml0eTELMAkGA1UECwwCRzMxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJ" "\n" 318 | "BgNVBAYTAlVTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2PWJ/KhZ" "\n" 319 | "C4fHTJEuLVaQ03gdpDDppUjvC0O/LYT7JF1FG+XrWTYSXFRknmxiLbTGl8rMPPbW" "\n" 320 | "BpH85QKmHGq0edVny6zpPwcR4YS8Rx1mjjmi6LRJ7TrS4RBgeo6TjMrA2gzAg9Dj" "\n" 321 | "+ZHWp4zIwXPirkbRYp2SqJBgN31ols2N4Pyb+ni743uvLRfdW/6AWSN1F7gSwe0b" "\n" 322 | "5TTO/iK1nkmw5VW/j4SiPKi6xYaVFuQAyZ8D0MyzOhZ71gVcnetHrg21LYwOaU1A" "\n" 323 | "0EtMOwSejSGxrC5DVDDOwYqGlJhL32oNP/77HK6XF8J4CjDgXx9UO0m3JQAaN4LS" "\n" 324 | "VpelUkl8YDib7wIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0j" "\n" 325 | "BBgwFoAUK9BpR5R2Cf70a40uQKb3R01/CF4wRAYIKwYBBQUHAQEEODA2MDQGCCsG" "\n" 326 | "AQUFBzABhihodHRwOi8vb2NzcC5hcHBsZS5jb20vb2NzcDAzLWFwcGxlcm9vdGNh" "\n" 327 | "MC4GA1UdHwQnMCUwI6AhoB+GHWh0dHA6Ly9jcmwuYXBwbGUuY29tL3Jvb3QuY3Js" "\n" 328 | "MB0GA1UdDgQWBBQJ/sAVkPmvZAqSErkmKGMMl+ynsjAOBgNVHQ8BAf8EBAMCAQYw" "\n" 329 | "EAYKKoZIhvdjZAYCAQQCBQAwDQYJKoZIhvcNAQELBQADggEBAK1lE+j24IF3RAJH" "\n" 330 | "Qr5fpTkg6mKp/cWQyXMT1Z6b0KoPjY3L7QHPbChAW8dVJEH4/M/BtSPp3Ozxb8qA" "\n" 331 | "HXfCxGFJJWevD8o5Ja3T43rMMygNDi6hV0Bz+uZcrgZRKe3jhQxPYdwyFot30ETK" "\n" 332 | "XXIDMUacrptAGvr04NM++i+MZp+XxFRZ79JI9AeZSWBZGcfdlNHAwWx/eCHvDOs7" "\n" 333 | "bJmCS1JgOLU5gm3sUjFTvg+RTElJdI+mUcuER04ddSduvfnSXPN/wmwLCTbiZOTC" "\n" 334 | "NwMUGdXqapSqqdv+9poIZ4vvK7iqF0mDr8/LvOnP6pVxsLRFoszlh6oKw0E6eVza" "\n" 335 | "UDSdlTs=" "\n" 336 | "-----END CERTIFICATE-----" "\n"; 337 | 338 | int status = 0; 339 | if (g3) { 340 | status = isRevokedByOCSP(x509, g3_issuer1_bytes); 341 | } else { 342 | status = isRevokedByOCSP(x509, issuer1_bytes); 343 | } 344 | 345 | return status == -1; 346 | } 347 | 348 | //根据证书组织单位来判断使用哪个根证书来检查 349 | //G2 350 | /* 351 | 352 | const char issuer1_bytes[] = "-----BEGIN CERTIFICATE-----" "\n" 353 | "MIIEIjCCAwqgAwIBAgIIAd68xDltoBAwDQYJKoZIhvcNAQEFBQAwYjELMAkGA1UE" "\n" 354 | "BhMCVVMxEzARBgNVBAoTCkFwcGxlIEluYy4xJjAkBgNVBAsTHUFwcGxlIENlcnRp" "\n" 355 | "ZmljYXRpb24gQXV0aG9yaXR5MRYwFAYDVQQDEw1BcHBsZSBSb290IENBMB4XDTEz" "\n" 356 | "MDIwNzIxNDg0N1oXDTIzMDIwNzIxNDg0N1owgZYxCzAJBgNVBAYTAlVTMRMwEQYD" "\n" 357 | "VQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3JsZHdpZGUgRGV2ZWxv" "\n" 358 | "cGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3aWRlIERldmVsb3Bl" "\n" 359 | "ciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3" "\n" 360 | "DQEBAQUAA4IBDwAwggEKAoIBAQDKOFSmy1aqyCQ5SOmM7uxfuH8mkbw0U3rOfGOA" "\n" 361 | "YXdkXqUHI7Y5/lAtFVZYcC1+xG7BSoU+L/DehBqhV8mvexj/avoVEkkVCBmsqtsq" "\n" 362 | "Mu2WY2hSFT2Miuy/axiV4AOsAX2XBWfODoWVN2rtCbauZ81RZJ/GXNG8V25nNYB2" "\n" 363 | "NqSHgW44j9grFU57Jdhav06DwY3Sk9UacbVgnJ0zTlX5ElgMhrgWDcHld0WNUEi6" "\n" 364 | "Ky3klIXh6MSdxmilsKP8Z35wugJZS3dCkTm59c3hTO/AO0iMpuUhXf1qarunFjVg" "\n" 365 | "0uat80YpyejDi+l5wGphZxWy8P3laLxiX27Pmd3vG2P+kmWrAgMBAAGjgaYwgaMw" "\n" 366 | "HQYDVR0OBBYEFIgnFwmpthhgi+zruvZHWcVSVKO3MA8GA1UdEwEB/wQFMAMBAf8w" "\n" 367 | "HwYDVR0jBBgwFoAUK9BpR5R2Cf70a40uQKb3R01/CF4wLgYDVR0fBCcwJTAjoCGg" "\n" 368 | "H4YdaHR0cDovL2NybC5hcHBsZS5jb20vcm9vdC5jcmwwDgYDVR0PAQH/BAQDAgGG" "\n" 369 | "MBAGCiqGSIb3Y2QGAgEEAgUAMA0GCSqGSIb3DQEBBQUAA4IBAQBPz+9Zviz1smwv" "\n" 370 | "j+4ThzLoBTWobot9yWkMudkXvHcs1Gfi/ZptOllc34MBvbKuKmFysa/Nw0Uwj6OD" "\n" 371 | "Dc4dR7Txk4qjdJukw5hyhzs+r0ULklS5MruQGFNrCk4QttkdUGwhgAqJTleMa1s8" "\n" 372 | "Pab93vcNIx0LSiaHP7qRkkykGRIZbVf1eliHe2iK5IaMSuviSRSqpd1VAKmuu0sw" "\n" 373 | "ruGgsbwpgOYJd+W+NKIByn/c4grmO7i77LpilfMFY0GCzQ87HUyVpNur+cmV6U/k" "\n" 374 | "TecmmYHpvPm0KdIBembhLoz2IYrF+Hjhga6/05Cdqa3zr/04GpZnMBxRpVzscYqC" "\n" 375 | "tGwPDBUf" "\n" 376 | "-----END CERTIFICATE-----" "\n"; 377 | */ 378 | 379 | 380 | //G3 381 | /* 382 | const char issuer1_bytes[] = "-----BEGIN CERTIFICATE-----" "\n" 383 | "MIIEUTCCAzmgAwIBAgIQfK9pCiW3Of57m0R6wXjF7jANBgkqhkiG9w0BAQsFADBi" "\n" 384 | "MQswCQYDVQQGEwJVUzETMBEGA1UEChMKQXBwbGUgSW5jLjEmMCQGA1UECxMdQXBw" "\n" 385 | "bGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNVBAMTDUFwcGxlIFJvb3Qg" "\n" 386 | "Q0EwHhcNMjAwMjE5MTgxMzQ3WhcNMzAwMjIwMDAwMDAwWjB1MUQwQgYDVQQDDDtB" "\n" 387 | "cHBsZSBXb3JsZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9ucyBDZXJ0aWZpY2F0aW9u" "\n" 388 | "IEF1dGhvcml0eTELMAkGA1UECwwCRzMxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJ" "\n" 389 | "BgNVBAYTAlVTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2PWJ/KhZ" "\n" 390 | "C4fHTJEuLVaQ03gdpDDppUjvC0O/LYT7JF1FG+XrWTYSXFRknmxiLbTGl8rMPPbW" "\n" 391 | "BpH85QKmHGq0edVny6zpPwcR4YS8Rx1mjjmi6LRJ7TrS4RBgeo6TjMrA2gzAg9Dj" "\n" 392 | "+ZHWp4zIwXPirkbRYp2SqJBgN31ols2N4Pyb+ni743uvLRfdW/6AWSN1F7gSwe0b" "\n" 393 | "5TTO/iK1nkmw5VW/j4SiPKi6xYaVFuQAyZ8D0MyzOhZ71gVcnetHrg21LYwOaU1A" "\n" 394 | "0EtMOwSejSGxrC5DVDDOwYqGlJhL32oNP/77HK6XF8J4CjDgXx9UO0m3JQAaN4LS" "\n" 395 | "VpelUkl8YDib7wIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0j" "\n" 396 | "BBgwFoAUK9BpR5R2Cf70a40uQKb3R01/CF4wRAYIKwYBBQUHAQEEODA2MDQGCCsG" "\n" 397 | "AQUFBzABhihodHRwOi8vb2NzcC5hcHBsZS5jb20vb2NzcDAzLWFwcGxlcm9vdGNh" "\n" 398 | "MC4GA1UdHwQnMCUwI6AhoB+GHWh0dHA6Ly9jcmwuYXBwbGUuY29tL3Jvb3QuY3Js" "\n" 399 | "MB0GA1UdDgQWBBQJ/sAVkPmvZAqSErkmKGMMl+ynsjAOBgNVHQ8BAf8EBAMCAQYw" "\n" 400 | "EAYKKoZIhvdjZAYCAQQCBQAwDQYJKoZIhvcNAQELBQADggEBAK1lE+j24IF3RAJH" "\n" 401 | "Qr5fpTkg6mKp/cWQyXMT1Z6b0KoPjY3L7QHPbChAW8dVJEH4/M/BtSPp3Ozxb8qA" "\n" 402 | "HXfCxGFJJWevD8o5Ja3T43rMMygNDi6hV0Bz+uZcrgZRKe3jhQxPYdwyFot30ETK" "\n" 403 | "XXIDMUacrptAGvr04NM++i+MZp+XxFRZ79JI9AeZSWBZGcfdlNHAwWx/eCHvDOs7" "\n" 404 | "bJmCS1JgOLU5gm3sUjFTvg+RTElJdI+mUcuER04ddSduvfnSXPN/wmwLCTbiZOTC" "\n" 405 | "NwMUGdXqapSqqdv+9poIZ4vvK7iqF0mDr8/LvOnP6pVxsLRFoszlh6oKw0E6eVza" "\n" 406 | "UDSdlTs=" "\n" 407 | "-----END CERTIFICATE-----" "\n"; 408 | */ 409 | --------------------------------------------------------------------------------