├── DES ├── DES.exe ├── DES算法的程序设计和实现实验实验报告.pdf └── DES.cpp ├── MD5 ├── MD5.exe ├── MD5算法的程序设计和实现实验实验报告.pdf └── MD5.cpp ├── X.509 ├── Reader.o ├── Reader.exe ├── DER_x509.cer ├── X509证书解析程序设计和实现实验实验报告.pdf ├── X509证书结构解析.txt └── Reader.cpp ├── IPSec └── IPSec传输模式下ESP 报文的装包与拆包过程.pdf ├── README.md └── LICENSE /DES/DES.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZTao-z/WebSecurity/HEAD/DES/DES.exe -------------------------------------------------------------------------------- /MD5/MD5.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZTao-z/WebSecurity/HEAD/MD5/MD5.exe -------------------------------------------------------------------------------- /X.509/Reader.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZTao-z/WebSecurity/HEAD/X.509/Reader.o -------------------------------------------------------------------------------- /X.509/Reader.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZTao-z/WebSecurity/HEAD/X.509/Reader.exe -------------------------------------------------------------------------------- /X.509/DER_x509.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZTao-z/WebSecurity/HEAD/X.509/DER_x509.cer -------------------------------------------------------------------------------- /DES/DES算法的程序设计和实现实验实验报告.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZTao-z/WebSecurity/HEAD/DES/DES算法的程序设计和实现实验实验报告.pdf -------------------------------------------------------------------------------- /MD5/MD5算法的程序设计和实现实验实验报告.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZTao-z/WebSecurity/HEAD/MD5/MD5算法的程序设计和实现实验实验报告.pdf -------------------------------------------------------------------------------- /X.509/X509证书解析程序设计和实现实验实验报告.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZTao-z/WebSecurity/HEAD/X.509/X509证书解析程序设计和实现实验实验报告.pdf -------------------------------------------------------------------------------- /IPSec/IPSec传输模式下ESP 报文的装包与拆包过程.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZTao-z/WebSecurity/HEAD/IPSec/IPSec传输模式下ESP 报文的装包与拆包过程.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WebSecurity 2 | 3 | ### 包含以下几个方面内容: 4 | 5 | (1)DES算法实现 6 | 7 | (2)MD5算法实现 8 | 9 | (3)X.509证书解析 10 | 11 | (4)IPsec传输模式的装包与拆包 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 ZTao-z 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /X.509/X509证书结构解析.txt: -------------------------------------------------------------------------------- 1 | Certificate ::= SEQUENCE { 2 | tbsCertificate TBSCertificate, -- 证书主体 3 | signatureAlgorithm AlgorithmIdentifier, -- 证书签名算法标识 4 | signatureValue BIT STRING -- 证书签名值,是使用signatureAlgorithm部分指定的签名算法 5 | 对tbsCertificate证书主题部分签名后的值. 6 | } 7 | 8 | TBSCertificate ::= SEQUENCE { 9 | version [0] EXPLICIT Version DEFAULT v1, -- 证书版本号 10 | serialNumber CertificateSerialNumber, -- 证书序列号,对同一CA所颁发的证书,序列号唯一标识证书 11 | signature AlgorithmIdentifier, -- 证书签名算法标识 12 | issuer Name, -- 证书发行者名称 13 | validity Validity, -- 证书有效期 14 | subject Name, -- 证书主体名称 15 | subjectPublicKeyInfo SubjectPublicKeyInfo, -- 证书公钥 16 | issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, -- 证书发行者ID(可选),只在证书版本2、3中才有 17 | subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, -- 证书主体ID(可选),只在证书版本2、3中才有 18 | extensions [3] EXPLICIT Extensions OPTIONAL -- 证书扩展段(可选),只在证书版本3中才有 19 | } 20 | 21 | Version ::= INTEGER { v1(0), v2(1), v3(2) } -- 版本号(v1,v2,v3) 22 | 23 | CertificateSerialNumber ::= INTEGER -- 证书序列号存储结构 24 | 25 | AlgorithmIdentifier ::= SEQUENCE { -- 签名算法标识存储结构 26 | algorithm OBJECT IDENTIFIER, -- 签名算法名称 27 | parameters ANY DEFINED BY algorithm OPTIONAL -- 签名算法参数 28 | } 29 | 30 | parameters: -- DSA(DSS)算法时的参数,RSA算法没有此参数 31 | Dss-Parms ::= SEQUENCE { 32 | p INTEGER, 33 | q INTEGER, 34 | g INTEGER 35 | } 36 | 37 | signatureValue: -- sha1DSA签名算法时,签名值存储结构 38 | Dss-Sig-Value ::= SEQUENCE { 39 | r INTEGER, 40 | s INTEGER 41 | } 42 | 43 | Name ::= CHOICE { -- 证书发行者名称存储结构 44 | RDNSequence 45 | } 46 | 47 | RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 48 | 49 | RelativeDistinguishedName ::= SET OF AttributeTypeAndValue 50 | 51 | AttributeTypeAndValue ::= SEQUENCE { 52 | type AttributeType, 53 | value AttributeValue 54 | } 55 | 56 | AttributeType ::= OBJECT IDENTIFIER 57 | 58 | AttributeValue ::= ANY DEFINED BY AttributeType 59 | 60 | Validity ::= SEQUENCE { -- 证书有效期存储结构 61 | notBefore Time, -- 证书有效期起始时间 62 | notAfter Time -- 证书有效期终止时间 63 | } 64 | 65 | Time ::= CHOICE { 66 | utcTime UTCTime, 67 | generalTime GeneralizedTime 68 | } 69 | 70 | UniqueIdentifier ::= BIT STRING -- 证书唯一标识存储结构 71 | 72 | SubjectPublicKeyInfo ::= SEQUENCE { -- 证书公钥存储结构 73 | algorithm AlgorithmIdentifier, -- 公钥算法 74 | subjectPublicKey BIT STRING -- 公钥值 75 | } 76 | 77 | subjectPublicKey: -- RSA算法时的公钥值 78 | RSAPublicKey ::= SEQUENCE { 79 | modulus INTEGER, 80 | publicExponent INTEGER 81 | } 82 | 83 | Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension -- 拓展部分存储结构 84 | Extension ::= SEQUENCE { 85 | extnID OBJECT IDENTIFIER, 86 | critical BOOLEAN DEFAULT FALSE, 87 | extnValue OCTET STRING 88 | } 89 | 90 | 91 | -------------------------------------------------------------------------------- /MD5/MD5.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | #define A 0x67452301 9 | #define B 0xefcdab89 10 | #define C 0x98badcfe 11 | #define D 0x10325476 12 | 13 | const char str16[] = "0123456789abcdef"; 14 | 15 | const unsigned int T[] = { 16 | 0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee, 17 | 0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501, 18 | 0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be, 19 | 0x6b901122,0xfd987193,0xa679438e,0x49b40821, 20 | 0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa, 21 | 0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8, 22 | 0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed, 23 | 0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a, 24 | 0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c, 25 | 0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70, 26 | 0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05, 27 | 0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665, 28 | 0xf4292244,0x432aff97,0xab9423a7,0xfc93a039, 29 | 0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1, 30 | 0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1, 31 | 0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391 }; 32 | 33 | const unsigned int s[] = { 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22, 34 | 5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20, 35 | 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23, 36 | 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21}; 37 | class MD5 { 38 | private: 39 | unsigned int tempA, tempB, tempC, tempD, strlength; 40 | public: 41 | MD5() { 42 | tempA = A; 43 | tempB = B; 44 | tempC = C; 45 | tempD = D; 46 | strlength = 0; 47 | } 48 | // F函数 49 | unsigned int F(unsigned int b, unsigned int c, unsigned int d) { 50 | return (b & c) | ((~b) & d); 51 | } 52 | // G函数 53 | unsigned int G(unsigned int b, unsigned int c, unsigned int d) { 54 | return (b & d) | (c & (~d)); 55 | } 56 | // H函数 57 | unsigned int H(unsigned int b, unsigned int c, unsigned int d) { 58 | return b ^ c ^ d; 59 | } 60 | // I函数 61 | unsigned int I(unsigned int b, unsigned int c, unsigned int d) { 62 | return c ^ (b | (~d)); 63 | } 64 | // 移位操作函数 65 | unsigned int shift(unsigned int a, unsigned int n) { 66 | return (a << n) | (a >> (32 - n)); 67 | } 68 | // 编码函数 69 | string encode(string src) { 70 | vector rec = padding(src); 71 | for(unsigned int i = 0; i < strlength/16; i++) { 72 | unsigned int num[16]; 73 | for(int j = 0; j < 16; j++) { 74 | num[j] = rec[i*16+j]; 75 | } 76 | iterateFunc(num, 16); 77 | } 78 | return format(tempA) + format(tempB) + format(tempC) + format(tempD); 79 | } 80 | // 循环压缩 81 | void iterateFunc(unsigned int* X, int size = 16) { 82 | unsigned int a = tempA, 83 | b = tempB, 84 | c = tempC, 85 | d = tempD, 86 | rec = 0, 87 | g, k; 88 | for(int i = 0; i < 64; i++) { 89 | if(i < 16) { 90 | // F迭代 91 | g = F(b, c, d); 92 | k = i; 93 | } 94 | else if(i < 32) { 95 | // G迭代 96 | g = G(b, c, d); 97 | k = (1 + 5*i) % 16; 98 | } 99 | else if(i < 48) { 100 | // H迭代 101 | g = H(b, c, d); 102 | k = (5 + 3*i) % 16; 103 | } 104 | else { 105 | // I迭代 106 | g = I(b, c, d); 107 | k = (7*i) % 16; 108 | } 109 | rec = d; 110 | d = c; 111 | c = b; 112 | b = b + shift(a + g + X[k] + T[i], s[i]); 113 | a = rec; 114 | } 115 | tempA += a; 116 | tempB += b; 117 | tempC += c; 118 | tempD += d; 119 | } 120 | // 填充字符串 121 | vector padding(string src) { 122 | // 以512位,64个字节为一组 123 | unsigned int num = ((src.length() + 8) / 64) + 1; 124 | vector rec(num*16); 125 | strlength = num*16; 126 | for(unsigned int i = 0; i < src.length(); i++){ 127 | // 一个unsigned int对应4个字节,保存4个字符信息 128 | rec[i>>2] |= (int)(src[i]) << ((i % 4) * 8); 129 | } 130 | // 补充1000...000 131 | rec[src.length() >> 2] |= (0x80 << ((src.length() % 4)*8)); 132 | // 填充原文长度 133 | rec[rec.size()-2] = (src.length() << 3); 134 | return rec; 135 | } 136 | // 整理输出 137 | string format(unsigned int num) { 138 | string res = ""; 139 | unsigned int base = 1 << 8; 140 | for(int i = 0; i < 4; i++) { 141 | string tmp = ""; 142 | unsigned int b = (num >> (i * 8)) % base & 0xff; 143 | for(int j = 0; j < 2; j++) { 144 | tmp = str16[b%16] + tmp; 145 | b /= 16; 146 | } 147 | res += tmp; 148 | } 149 | return res; 150 | } 151 | }; 152 | 153 | int main() { 154 | MD5 test; 155 | string a = ""; 156 | cout << "Plain Text: "; 157 | getline(cin,a); 158 | cout << "result: " << test.encode(a) << endl; 159 | } 160 | -------------------------------------------------------------------------------- /DES/DES.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define DEBUG 0 8 | 9 | using namespace std; 10 | 11 | const int IP[64] = { 58,50,42,34,26,18,10,2, 12 | 60,52,44,36,28,20,12,4, 13 | 62,54,46,38,30,22,14,6, 14 | 64,56,48,40,32,24,16,8, 15 | 57,49,41,33,25,17, 9,1, 16 | 59,51,43,35,27,19,11,3, 17 | 61,53,45,37,29,21,13,5, 18 | 63,55,47,39,31,23,15,7 }; 19 | 20 | const int IP_1[64] = { 40,8,48,16,56,24,64,32, 21 | 39,7,47,15,55,23,63,31, 22 | 38,6,46,14,54,22,62,30, 23 | 37,5,45,13,53,21,61,29, 24 | 36,4,44,12,52,20,60,28, 25 | 35,3,43,11,51,19,59,27, 26 | 34,2,42,10,50,18,58,26, 27 | 33,1,41,9,49,17,57,25 }; 28 | 29 | const int E_exp[48] = { 32,1,2,3,4,5, 30 | 4,5,6,7,8,9, 31 | 8,9,10,11,12,13, 32 | 12,13,14,15,16,17, 33 | 16,17,18,19,20,21, 34 | 20,21,22,23,24,25, 35 | 24,25,26,27,28,29, 36 | 28,29,30,31,32,1}; 37 | 38 | const int P_transform[32] = { 16,7,20,21, 39 | 29,12,28,17, 40 | 1,15,23,26, 41 | 5,18,31,10, 42 | 2,8,24,14, 43 | 32,27,3,9, 44 | 19,13,30,6, 45 | 22,11,4,25}; 46 | 47 | const int PC_1[56] = { 57,49,41,33,25,17,9, 48 | 1,58,50,42,34,26,18, 49 | 10,2,59,51,43,35,27, 50 | 19,11,3,60,52,44,36, 51 | 63,55,47,39,31,23,15, 52 | 7,62,54,46,38,30,22, 53 | 14,6,61,53,45,37,29, 54 | 21,13,5,28,20,12,4}; 55 | 56 | const int PC_2[56] = { 14,17,11,24,1,5, 57 | 3,28,15,6,21,10, 58 | 23,19,12,4,26,8, 59 | 16,7,27,20,13,2, 60 | 41,52,31,37,47,55, 61 | 30,40,51,45,33,48, 62 | 44,49,39,56,34,53, 63 | 46,42,50,36,29,32}; 64 | 65 | const int SBOX_1[4][16] = {{14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7}, 66 | {0,15,7,4,15,2,13,1,10,6,12,11,9,5,3,8}, 67 | {4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0}, 68 | {15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13}}; 69 | 70 | const int SBOX_2[4][16] = {{15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10}, 71 | {3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5}, 72 | {0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15}, 73 | {13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9}}; 74 | 75 | const int SBOX_3[4][16] = {{10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8}, 76 | {13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1}, 77 | {13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7}, 78 | {1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12}}; 79 | 80 | const int SBOX_4[4][16] = {{7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15}, 81 | {12,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9}, 82 | {10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4}, 83 | {3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14}}; 84 | 85 | const int SBOX_5[4][16] = {{2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9}, 86 | {14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6}, 87 | {4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14}, 88 | {11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3}}; 89 | 90 | const int SBOX_6[4][16] = {{12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11}, 91 | {10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8}, 92 | {9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6}, 93 | {4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13}}; 94 | 95 | const int SBOX_7[4][16] = {{4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1}, 96 | {13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6}, 97 | {1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2}, 98 | {6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12}}; 99 | 100 | const int SBOX_8[4][16] = {{13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7}, 101 | {1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2}, 102 | {7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8}, 103 | {2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11}}; 104 | 105 | typedef const int (*SBOX)[16]; 106 | SBOX SBox[8] = { SBOX_1, SBOX_2, SBOX_3, SBOX_4, SBOX_5, SBOX_6, SBOX_7, SBOX_8}; 107 | 108 | class DES{ 109 | private: 110 | string total_code, total_key; 111 | string tempCode_1, tempCode_2; 112 | string m_code, code; 113 | string L, R, C, D; 114 | vector K; 115 | public: 116 | DES() {} 117 | // 加密 118 | void encode(string str, string key) { 119 | m_code = ""; 120 | total_code = str; 121 | total_key = key; 122 | if(DEBUG) { 123 | cout << "getkeys" << endl; 124 | } 125 | getKeys(); 126 | if(DEBUG) { 127 | cout << "formatSourceCode" << endl; 128 | } 129 | formatSourceCode(); 130 | int count = 0; 131 | int s = total_code.size(); 132 | while(count*8 < s) { 133 | string sub; 134 | if(s-count*8 >= 8){ 135 | sub = total_code.substr(count*8, 8); 136 | } 137 | else{ 138 | sub = total_code.substr(count*8); 139 | } 140 | count++; 141 | fill(sub); 142 | if(DEBUG) { 143 | cout << "code length: "<< tempCode_1.size() << endl; 144 | } 145 | if(DEBUG) { 146 | cout << "IP0" << endl; 147 | } 148 | getIP0(); 149 | if(DEBUG) { 150 | cout << "iterationT" << endl; 151 | } 152 | string a = iterationT_A(1, 16); 153 | if(DEBUG) { 154 | cout << "IP1" << endl; 155 | } 156 | string result = getIP1(a); 157 | m_code += result; 158 | if(DEBUG) { 159 | cout << result.size() << endl; 160 | } 161 | } 162 | cout << m_code << endl; 163 | } 164 | // 解密 165 | void decode(string str, string key) { 166 | int count = 0; 167 | code = ""; 168 | getKeys(); 169 | while(count*64 < str.size()){ 170 | tempCode_1 = str.substr(count*64, 64); 171 | total_key = key; 172 | count++; 173 | if(DEBUG) { 174 | cout << "K :" << endl; 175 | for(int i = 0; i < K.size(); i++) { 176 | cout << K[i] < 0) { 206 | s = (char)(a%2+48) + s; 207 | a /= 2; 208 | } 209 | while(s.size() < 8) { 210 | s = "0" + s; 211 | } 212 | tempCode_1 += s; 213 | } 214 | if(DEBUG) { 215 | cout << tempCode_1 << endl; 216 | } 217 | } 218 | // 填充字符串 219 | void formatSourceCode() { 220 | if(total_code.size() % 8 == 0) { 221 | total_code += "\b\b\b\b\b\b\b\b"; 222 | } 223 | } 224 | // IP置换(LR) 225 | void getIP0() { 226 | tempCode_2 = tempCode_1; 227 | L = ""; 228 | R = ""; 229 | for(int i = 0; i < 64; i++) { 230 | tempCode_2[i] = tempCode_1[IP[i]-1]; 231 | } 232 | for(int i = 0; i < 64; i++) { 233 | if(i < 32){ 234 | L += tempCode_2[i]; 235 | } 236 | else { 237 | R += tempCode_2[i]; 238 | } 239 | } 240 | 241 | if(DEBUG) { 242 | cout << "tempCode_2: " << tempCode_2 << endl; 243 | cout << "L: " << L << endl; 244 | cout << "R: " << R << endl; 245 | } 246 | } 247 | // Feistel轮函数 248 | string Feistel(string R, string K) { 249 | string res = "", rec = ""; 250 | // 将长度为32位的串 Ri-1 作 E-扩展 251 | string ER = E_expend(R); 252 | // E(Ri-1) 和长度为48位的子密钥 Ki 作异或运算 253 | for(int i = 0; i < 48; i++) { 254 | res += (char)(((ER[i]-48) ^ (K[i]-48))+48); 255 | } 256 | // 平均分成8个分组, 分别经过8个不同的 S-盒进行 6-4 转换 257 | for(int i = 0; i < 8; i++) { 258 | string sub = res.substr(i*6, 6); 259 | string sub_m = Feistel_SBOX(sub, i); 260 | // 顺序连接得到长度为32位的串 261 | rec += sub_m; 262 | } 263 | if(DEBUG) { 264 | cout << "substring length: " << rec.size() << endl; 265 | } 266 | // P-置换 267 | return getPTransform(rec); 268 | } 269 | // P置换 270 | string getPTransform(string str) { 271 | string res = ""; 272 | for(int i = 0; i < 32; i++) { 273 | res += str[P_transform[i]-1]; 274 | } 275 | return res; 276 | } 277 | // Feistel SBOX 278 | string Feistel_SBOX(string str, int num){ 279 | int n = (str[0]-48) * 2 + (str[5]-48); 280 | int m = (str[1]-48) * 8 + (str[2]-48) * 4 + (str[3]-48) * 2 + (str[4]-48); 281 | int number = SBox[num][n][m]; 282 | string res = ""; 283 | while(number > 0) { 284 | res = (char)(number%2+48) + res; 285 | number /= 2; 286 | } 287 | while(res.size() < 4) { 288 | res = "0" + res; 289 | } 290 | if(DEBUG) { 291 | cout << "SBox: " << endl; 292 | cout << str << " " << num << " " << res << endl; 293 | } 294 | return res; 295 | } 296 | // E扩展 297 | string E_expend(string str) { 298 | string res = ""; 299 | for(int i = 0; i < 48; i++) { 300 | res += str[E_exp[i]-1]; 301 | } 302 | if(DEBUG) { 303 | cout << "E expend: " << res << endl; 304 | } 305 | return res; 306 | } 307 | // XOR操作 308 | string XORoperation(string a, string b) { 309 | string res = ""; 310 | for(int i = 0; i < 32; i++) { 311 | res += (char)(((a[i]-48) ^ (b[i]-48))+48); 312 | } 313 | return res; 314 | } 315 | // T迭代(加密) 316 | string iterationT_A(int begin, int end) { 317 | string L_temp, R_temp; 318 | for(int i = begin-1; i <= end-1; i++) { 319 | L_temp = R; 320 | R_temp = XORoperation(L, Feistel(R, K[i])); 321 | L = L_temp; 322 | R = R_temp; 323 | } 324 | return R+L; 325 | } 326 | // T迭代(解密) 327 | string iterationT_D(int begin, int end) { 328 | string L_temp, R_temp; 329 | for(int i = begin-1; i >= end-1; i--) { 330 | L_temp = R; 331 | R_temp = XORoperation(L, Feistel(R, K[i])); 332 | L = L_temp; 333 | R = R_temp; 334 | } 335 | return R+L; 336 | } 337 | // IP逆置换 338 | string getIP1(string str) { 339 | string res = ""; 340 | for(int i = 0; i < 64; i++) { 341 | res += str[IP_1[i]-1]; 342 | } 343 | return res; 344 | } 345 | // 整理明文1 346 | string formatResult(string str) { 347 | int count = 0; 348 | string res = ""; 349 | while(count*8 < str.size()) { 350 | string a = str.substr(count*8, 8); 351 | res += (char)(Two2Ten(a)); 352 | count++; 353 | } 354 | return res; 355 | } 356 | // 整理明文2 357 | string formatAndReduceResult(string str) { 358 | int count = 0; 359 | string res = ""; 360 | string a = str.substr(str.size()-8, 8); 361 | int n = (int)(Two2Ten(a)); 362 | if(DEBUG) { 363 | cout << a << endl; 364 | cout << n << endl; 365 | } 366 | while(count < 8-n) { 367 | a = str.substr(count*8, 8); 368 | res += (char)(Two2Ten(a)); 369 | count++; 370 | } 371 | return res; 372 | } 373 | // 二进制转十进制 374 | int Two2Ten(string num) { 375 | int base = 1; 376 | int res = 0; 377 | for(int i = num.size()-1; i >= 0; i--) { 378 | res += (int)(num[i]-48) * base; 379 | base *= 2; 380 | } 381 | return res; 382 | } 383 | // 子密钥部分 384 | // 子密钥格式化 385 | string formatKey() { 386 | string res = "", rec = ""; 387 | for(int i = 0; i < 8; i++) { 388 | int num = (int)total_key[i]; 389 | res = ""; 390 | while(num > 0) { 391 | res = (char)(num%2+48) + res; 392 | num /= 2; 393 | } 394 | while(res.size() < 8) { 395 | res = "0" + res; 396 | } 397 | rec += res; 398 | } 399 | if(DEBUG) { 400 | cout << "rec: " << rec << endl; 401 | } 402 | return rec; 403 | } 404 | // PC1置换 405 | string getPC1Key(string str) { 406 | string res = str; 407 | for(int i = 0; i < 56; i++) { 408 | res[i] = str[PC_1[i]-1]; 409 | } 410 | if(DEBUG){ 411 | cout << "res: " << res << endl; 412 | } 413 | return res; 414 | } 415 | // 获取C、D 416 | void get_C_D(string str) { 417 | C = ""; 418 | D = ""; 419 | str.erase(63,1); 420 | str.erase(55,1); 421 | str.erase(47,1); 422 | str.erase(39,1); 423 | str.erase(31,1); 424 | str.erase(23,1); 425 | str.erase(15,1); 426 | str.erase(7,1); 427 | for(int i = 0; i < str.size(); i++) { 428 | if(i < 28) { 429 | C += str[i]; 430 | } 431 | else { 432 | D += str[i]; 433 | } 434 | } 435 | if(DEBUG) { 436 | cout << "C: " << C << endl; 437 | cout << "D: " << D << endl; 438 | } 439 | } 440 | // LS置换 441 | void getKeyI() { 442 | //string C_temp = C, D_temp = D; 443 | for(int i = 1; i <= 16; i++) { 444 | if(i == 1 || i == 2 || i == 9 || i == 16) { 445 | LS_1(C); 446 | LS_1(D); 447 | } 448 | else { 449 | LS_2(C); 450 | LS_2(D); 451 | } 452 | string t = C+D; 453 | t = getPC2Key(t); 454 | K.push_back(t); 455 | } 456 | } 457 | // LS置换(1) 458 | void LS_1(string& str) { 459 | char a = str[0]; 460 | for(int i = 0; i < str.size()-1; i++) { 461 | str[i] = str[i+1]; 462 | } 463 | str[str.size()-1] = a; 464 | } 465 | // LS置换(2) 466 | void LS_2(string& str) { 467 | char a = str[0], b = str[1]; 468 | for(int i = 0; i < str.size()-2; i++) { 469 | str[i] = str[i+2]; 470 | } 471 | str[str.size()-2] = a; 472 | str[str.size()-1] = b; 473 | } 474 | // PC2置换 475 | string getPC2Key(string str) { 476 | string res = str; 477 | for(int i = 0; i < 48; i++) { 478 | res[i] = str[PC_2[i]-1]; 479 | } 480 | res.erase(53,1); 481 | res.erase(42,1); 482 | res.erase(37,1); 483 | res.erase(34,1); 484 | res.erase(24,1); 485 | res.erase(21,1); 486 | res.erase(17,1); 487 | res.erase(8,1); 488 | return res; 489 | } 490 | // 获取子密钥的总函数 491 | void getKeys() { 492 | vector t; 493 | K = t; 494 | string a = formatKey(); 495 | a = getPC1Key(a); 496 | get_C_D(a); 497 | getKeyI(); 498 | } 499 | }; 500 | 501 | int main() { 502 | string c, k; 503 | cout << "Plaintext: "; 504 | cin >> c; 505 | cout << "Key: "; 506 | cin >> k; 507 | DES des; 508 | cout << "result: "; 509 | des.encode(c, k); 510 | cout << endl; 511 | cout << "Ciphertext: "; 512 | cin >> c; 513 | cout << "Key: "; 514 | cin >> k; 515 | cout << "result: "; 516 | des.decode(c, k); 517 | return 0; 518 | } 519 | -------------------------------------------------------------------------------- /X.509/Reader.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | struct Seg { 10 | int num; 11 | Seg(unsigned char s){ 12 | num = (int)s; 13 | }; 14 | Seg() { 15 | num = -1; 16 | } 17 | }; 18 | 19 | typedef struct Seg Seg; 20 | 21 | struct TLV { 22 | Seg type; 23 | vector length; 24 | vector value; 25 | }; 26 | 27 | typedef struct TLV TLV; 28 | 29 | struct SignatureAlgorithm { 30 | TLV algorithm; 31 | TLV parameters; 32 | }; 33 | 34 | struct subjectPublicKey { 35 | TLV algorithm; 36 | TLV parameters; 37 | TLV PKey; 38 | }; 39 | 40 | struct SignatureValue { 41 | TLV signatureValue; 42 | }; 43 | 44 | struct signatureArray { 45 | TLV s1, s2; 46 | }; 47 | 48 | typedef struct SignatureAlgorithm SignatureAlgorithm; 49 | typedef struct subjectPublicKey subjectPublicKey; 50 | typedef struct SignatureValue SignatureValue; 51 | typedef struct signatureArray signatureArray; 52 | 53 | struct TbsCertificate{ 54 | TLV version; 55 | TLV serialNumber; 56 | SignatureAlgorithm signature; 57 | vector issuer_; 58 | vector validity; 59 | vector subject_; 60 | subjectPublicKey subjectPublicKeyInfo; 61 | TLV issuerUniqueID; 62 | TLV subjectUniqueID; 63 | vector extensions; 64 | }; 65 | 66 | struct X509cer { 67 | struct TbsCertificate catb; 68 | struct SignatureAlgorithm casa; 69 | struct SignatureValue casv; 70 | }; 71 | 72 | class X509Reader { 73 | private: 74 | vector segList; 75 | vector tlvList; 76 | struct X509cer x509cert; 77 | map OIDMap; 78 | public: 79 | X509Reader() { 80 | OIDMap.insert(pair("1.2.840.10040.4.1","DSA")); 81 | OIDMap.insert(pair("1.2.840.10040.4.3","sha1DSA")); 82 | OIDMap.insert(pair("1.2.840.113549.1.1.1","RSA")); 83 | OIDMap.insert(pair("1.2.840.113549.1.1.2","md2RSA")); 84 | OIDMap.insert(pair("1.2.840.113549.1.1.3","md4RSA")); 85 | OIDMap.insert(pair("1.2.840.113549.1.1.4","md5RSA")); 86 | OIDMap.insert(pair("1.2.840.113549.1.1.5","sha1RSA")); 87 | OIDMap.insert(pair("1.2.840.113549.1.1.11","sha256RSA")); 88 | OIDMap.insert(pair("1.2.840.10045.2.1","ECC")); 89 | OIDMap.insert(pair("1.2.840.10045.3.1.7","ECDSA_P256")); 90 | 91 | OIDMap.insert(pair("2.5.4.6","C")); 92 | OIDMap.insert(pair("2.5.4.8","S")); 93 | OIDMap.insert(pair("2.5.4.7","L")); 94 | OIDMap.insert(pair("2.5.4.10","O")); 95 | OIDMap.insert(pair("2.5.4.11","OU")); 96 | OIDMap.insert(pair("2.5.4.3","CN")); 97 | } 98 | void loadFile(string filename) { 99 | std::ifstream file; 100 | file.open(filename.c_str(), ios::in|ios::binary); 101 | while(!file.eof()) { 102 | char first; 103 | file.read(&first, 1); 104 | segList.push_back(Seg((unsigned char)first)); 105 | } 106 | file.close(); 107 | } 108 | 109 | void compileContent() { 110 | for(int i = 0; i < segList.size(); ) { 111 | if(segList[i].num >> 6 == 2) { 112 | int n = segList[i].num & 0x1f; 113 | if(n == 3) { 114 | TLV t; 115 | t.type = segList[i]; 116 | if(segList[i+1].num <= 0x7f) { 117 | t.length.push_back(segList[i+1]); 118 | i += 2; 119 | } 120 | else { 121 | int l = segList[i+1].num-0x80; 122 | int s = 0, base = 1; 123 | for(int j = i+2+l-1; j >= i+2; j--) { 124 | s += segList[j].num * base; 125 | base *= 256; 126 | } 127 | for(int j = i+1; j < i+2+l; j++) { 128 | t.length.push_back(segList[j]); 129 | } 130 | i += 2+l; 131 | } 132 | tlvList.push_back(t); 133 | } 134 | else { 135 | TLV t; 136 | t.type = segList[i]; 137 | t.length.push_back(segList[i+1]); 138 | tlvList.push_back(t); 139 | i += 2; 140 | } 141 | } 142 | else { 143 | if(segList[i].num >> 5 == 1) { 144 | TLV t; 145 | t.type = segList[i]; 146 | if(segList[i+1].num <= 0x7f) { 147 | t.length.push_back(segList[i+1]); 148 | i += 2; 149 | } 150 | else { 151 | int l = segList[i+1].num-0x80; 152 | int s = 0, base = 1; 153 | for(int j = i+2+l-1; j >= i+2; j--) { 154 | s += segList[j].num * base; 155 | base *= 256; 156 | } 157 | for(int j = i+1; j < i+2+l; j++) { 158 | t.length.push_back(segList[j]); 159 | } 160 | i += 2+l; 161 | } 162 | tlvList.push_back(t); 163 | } 164 | else { 165 | TLV t; 166 | t.type = segList[i]; 167 | if(segList[i+1].num <= 0x7f) { 168 | t.length.push_back(segList[i+1]); 169 | for(int j = i+2; j < i+2+segList[i+1].num; j++) { 170 | t.value.push_back(segList[j]); 171 | } 172 | i += segList[i+1].num + 2; 173 | } 174 | else { 175 | int l = segList[i+1].num-0x80; 176 | int s = 0, base = 1; 177 | for(int j = i+2+l-1; j >= i+2; j--) { 178 | s += segList[j].num * base; 179 | base *= 256; 180 | } 181 | for(int j = i+1; j < i+2+l; j++) { 182 | t.length.push_back(segList[j]); 183 | } 184 | for(int j = i+2+l; j < i+2+l+s; j++) { 185 | t.value.push_back(segList[j]); 186 | } 187 | i += 2+l+s; 188 | } 189 | tlvList.push_back(t); 190 | } 191 | } 192 | } 193 | } 194 | 195 | void showX509() { 196 | int count = 0, extensionSize = 0; 197 | bool isExtension = false; 198 | bool isBlock31 = false; 199 | for(int i = 0; i < tlvList.size()-1; i++) { 200 | if(isExtension){ 201 | extensionSize -= 1 + tlvList[i].length.size() + tlvList[i].value.size(); 202 | } 203 | if(tlvList[i].type.num == 0x31) { 204 | isBlock31 = true; 205 | continue; 206 | } 207 | else { 208 | if(tlvList[i].type.num == 0x30 && isBlock31 == false) { 209 | count++; 210 | continue; 211 | } 212 | else if(tlvList[i].type.num == 0x30 && isBlock31 == true) { 213 | isBlock31 = false; 214 | continue; 215 | } 216 | else if(tlvList[i].type.num == 0xa3) { 217 | count++; 218 | isExtension = true; 219 | int base = 1; 220 | for(int j = tlvList[i].length.size()-1; j >= 1; j--){ 221 | extensionSize += tlvList[i].length[j].num * base; 222 | base *= 256; 223 | } 224 | continue; 225 | } 226 | } 227 | if(count == 2) { 228 | if(tlvList[i].type.num == 0xa0) { 229 | x509cert.catb.version = tlvList[i+1]; 230 | i++; 231 | } 232 | else{ 233 | x509cert.catb.serialNumber = tlvList[i]; 234 | } 235 | } 236 | else if(count == 3) { 237 | if(tlvList[i].type.num == 0x06) { 238 | x509cert.catb.signature.algorithm = tlvList[i]; 239 | } 240 | else { 241 | x509cert.catb.signature.parameters = tlvList[i]; 242 | } 243 | } 244 | else if(count == 4) { 245 | signatureArray a; 246 | if(tlvList[i].type.num == 0x06) { 247 | a.s1 = tlvList[i]; 248 | a.s2 = tlvList[i+1]; 249 | x509cert.catb.issuer_.push_back(a); 250 | i+=1; 251 | } 252 | } 253 | else if(count == 5) { 254 | x509cert.catb.validity.push_back(tlvList[i]); 255 | x509cert.catb.validity.push_back(tlvList[i+1]); 256 | i+=1; 257 | } 258 | else if(count == 6) { 259 | signatureArray a; 260 | if(tlvList[i].type.num == 0x06) { 261 | a.s1 = tlvList[i]; 262 | a.s2 = tlvList[i+1]; 263 | x509cert.catb.subject_.push_back(a); 264 | i+=1; 265 | } 266 | } 267 | else if(count == 8) { 268 | if(tlvList[i].type.num == 0x06) { 269 | subjectPublicKey sbk; 270 | sbk.algorithm = tlvList[i]; 271 | sbk.parameters = tlvList[i+1]; 272 | sbk.PKey = tlvList[i+2]; 273 | x509cert.catb.subjectPublicKeyInfo = sbk; 274 | i+=2; 275 | } 276 | } 277 | else if(count >= 9 && isExtension) { 278 | if(extensionSize >= 0) { 279 | x509cert.catb.extensions.push_back(tlvList[i]); 280 | } 281 | if(extensionSize == 0) { 282 | isExtension = false; 283 | } 284 | } 285 | else { 286 | if(tlvList[i].type.num == 0x06) { 287 | x509cert.casa.algorithm = tlvList[i]; 288 | x509cert.casa.parameters = tlvList[i+1]; 289 | x509cert.casv.signatureValue = tlvList[i+2]; 290 | i += 2; 291 | } 292 | } 293 | } 294 | } 295 | 296 | string formatDate(TLV& p) { 297 | string result = "20"; 298 | if(p.type.num == 0x17) { 299 | int count = 0; 300 | for(int i = 0; i < p.value.size()-1; i+=2){ 301 | result = result + (char)p.value[i].num + (char)p.value[i+1].num; 302 | if(count <= 1){ 303 | result += "/"; 304 | } 305 | else if(count == 2) { 306 | result += " "; 307 | } 308 | else if(count <= 4){ 309 | result += ":"; 310 | } 311 | count++; 312 | } 313 | return result + " GMT"; 314 | } 315 | else { 316 | return ""; 317 | } 318 | } 319 | 320 | string formatOID(TLV& p) { 321 | string result = ""; 322 | char num[9]; 323 | vector V; 324 | if(p.type.num == 0x06) { 325 | for(int i = 0; i < p.value.size(); i++){ 326 | if(i == 0) { 327 | int v2 = p.value[i].num % 40; 328 | int v1 = (p.value[i].num -v2) / 40; 329 | V.push_back(v1); 330 | V.push_back(v2); 331 | } 332 | else { 333 | int j = i, res = 0; 334 | int base = 128; 335 | while(p.value[j].num >= 0x80){ 336 | j++; 337 | } 338 | res = p.value[j].num; 339 | for(int k = j-1; k >= i; k--) { 340 | res += (p.value[k].num - 0x80) * base; 341 | base *= 128; 342 | } 343 | V.push_back(res); 344 | i = j; 345 | } 346 | } 347 | for(int i = 0; i < V.size(); i++) { 348 | sprintf(num, "%d",V[i]); 349 | result += num; 350 | if(i < V.size()-1){ 351 | result += "."; 352 | } 353 | } 354 | return OIDMap[result]; 355 | } 356 | else { 357 | return ""; 358 | } 359 | } 360 | 361 | void displayOrigin() { 362 | int count = 0; 363 | for(int i = 0; i < segList.size(); i++) { 364 | printf("%02x ", segList[i].num); 365 | count++; 366 | if(count == 16){ 367 | cout << endl; 368 | count = 0; 369 | } 370 | } 371 | } 372 | 373 | void displayTLVOrigin() { 374 | int count = 0; 375 | bool isBlock31 = false; 376 | for(int i = 0; i < tlvList.size(); i++) { 377 | if(tlvList[i].type.num == 0x31) { 378 | isBlock31 = true; 379 | } 380 | else { 381 | if(tlvList[i].type.num == 0x30 && isBlock31 == false) { 382 | count++; 383 | } 384 | else if(tlvList[i].type.num == 0x30 && isBlock31 == true) { 385 | isBlock31 = false; 386 | } 387 | else if(tlvList[i].type.num == 0xa3){ 388 | count++; 389 | } 390 | } 391 | cout << "Count: " << count << endl; 392 | printf("type: %02x ", tlvList[i].type); 393 | printf("length: "); 394 | for(int j = 0; j < tlvList[i].length.size(); j++) { 395 | printf("%02x ", tlvList[i].length[j]); 396 | } 397 | printf("value(%02x): ", tlvList[i].value.size()); 398 | for(int j = 0; j < tlvList[i].value.size(); j++) { 399 | printf("%02x ", tlvList[i].value[j]); 400 | } 401 | printf("\n"); 402 | } 403 | } 404 | 405 | void printValue(TLV& p, int mode = 0) { 406 | if(p.value.size() == 0){ 407 | printf("NULL"); 408 | } 409 | else{ 410 | for(int i = 0; i < p.value.size(); i++) { 411 | if(p.type.num == 0x03 && i == 0) continue; 412 | if(p.type.num == 0x13) { 413 | printf("%c", p.value[i].num); 414 | } 415 | else { 416 | if(mode == 0) { 417 | printf("%02x ", p.value[i].num); 418 | } 419 | else{ 420 | printf("%02x", p.value[i].num); 421 | } 422 | } 423 | 424 | } 425 | if (p.type.num == 0x0c) { 426 | printf("(UTF-8)"); 427 | } 428 | } 429 | printf("\n"); 430 | } 431 | 432 | void displayResult() { 433 | printf("Version: V%d\n", x509cert.catb.version.value[0].num+1); 434 | printf("SerialNumber: "); 435 | printValue(x509cert.catb.serialNumber, 1); 436 | printf("SignatureAlgorithm:\n Algorithm: "); 437 | cout << formatOID(x509cert.catb.signature.algorithm) << endl; 438 | printf(" Params: "); 439 | printValue(x509cert.catb.signature.parameters); 440 | printf("Issuer: \n"); 441 | for(int i = 0; i < x509cert.catb.issuer_.size(); i++) { 442 | cout << " " << formatOID(x509cert.catb.issuer_[i].s1); 443 | printf(" = "); 444 | printValue(x509cert.catb.issuer_[i].s2); 445 | } 446 | printf("Validity:\n notBefore: "); 447 | cout << formatDate(x509cert.catb.validity[0]) << endl; 448 | printf(" notAfter: "); 449 | cout << formatDate(x509cert.catb.validity[1]) << endl; 450 | printf("Subject:\n"); 451 | for(int i = 0; i < x509cert.catb.subject_.size(); i++) { 452 | cout << " " << formatOID(x509cert.catb.subject_[i].s1); 453 | printf(" = "); 454 | printValue(x509cert.catb.subject_[i].s2); 455 | } 456 | printf("subjectPublicKeyInfo:\n"); 457 | printf(" Algorithm: "); 458 | cout << formatOID(x509cert.catb.subjectPublicKeyInfo.algorithm) << endl; 459 | printf(" Params: "); 460 | printValue(x509cert.catb.subjectPublicKeyInfo.parameters); 461 | printf(" PKey: "); 462 | printValue(x509cert.catb.subjectPublicKeyInfo.PKey); 463 | printf("issuerUniqueID: "); 464 | printValue(x509cert.catb.issuerUniqueID); 465 | printf("subjectUniqueID: "); 466 | printValue(x509cert.catb.subjectUniqueID); 467 | printf("Extensions:\n"); 468 | printf(" Other: ellipsis\n"); 469 | /* 470 | for(int i = 0; i < x509cert.catb.extensions.size(); i++) { 471 | if(x509cert.catb.extensions[i].type.num == 0x01) { 472 | printf(" isCACertification: "); 473 | printValue(x509cert.catb.extensions[i]); 474 | printf(" Other: ellipsis\n"); 475 | break; 476 | } 477 | }*/ 478 | printf("SignatureAlgorithm:\n"); 479 | printf(" Algorithm: "); 480 | cout << formatOID(x509cert.casa.algorithm) << endl; 481 | printf(" Params: "); 482 | printValue(x509cert.casa.parameters); 483 | printf("SignatureValue: "); 484 | printValue(x509cert.casv.signatureValue); 485 | } 486 | }; 487 | 488 | int main() { 489 | X509Reader reader; 490 | reader.loadFile("DER_x509.cer"); 491 | //reader.displayOrigin(); 492 | reader.compileContent(); 493 | //reader.displayTLVOrigin(); 494 | reader.showX509(); 495 | reader.displayResult(); 496 | return 0; 497 | } 498 | --------------------------------------------------------------------------------