Forge 4 Transports PKI Message Digests TLS RSA






















































































- Slides: 86




Forge에 구현된 내용 4 Transports PKI Message Digests � TLS � RSA � SHA 1 � HTTP � RSA-KEM � SHA 256 � SSH � X. 509 � SHA 384 � XHR � PKCS#5 � SHA 512 � Sockets � PKCS#7 � MD 5 � PKCS#8 � HMAC Ciphers � CIPHER � PKCS#10 � AES � PKCS#12 � DES � ASN. 1 � RC 2 API 문서의 사용법 참조 https: //www. npmjs. com/package/node-forge Utilities � Prime � PRNG � Tasks � Utilities � Logging � Debugging � Flash Networking Support

Forge 설치 5 프로젝트 폴더 생성 � � > md forge > cd forge 서버측 패키지 � � � > npm install node-forge node_modules 폴더에 설치됨 서버측 프로그램에서 다음과 같이 불러서 사용 var forge = require('node-forge'); 클라이언트측 패키지 � � � > bower install forge bower_components 폴더에 설치됨 클라이언트 html 파일에서 forge. min. js 파일을 불러서 사용 <script src=bower_components₩forge₩dist₩forge. min. js></script>




해시함수 9 해시 알고리즘 � � � Md 5 Sha 1 Sha 256 Sha 384 Sha 512

해시함수 - Message Digest 10 API � � Message digest(Hash)를 위한 객체는 forge. md 구현된 해시 알고리즘: Sha 1, Sha 256, Sha 384, Sha 512, Md 5 사용 방법 � Create update digest var md = forge. md 5. create(); md. update('The quick brown fox jumps over the lazy dog'); console. log(md. digest(). to. Hex()); // output: 9 e 107 d 9 d 372 bb 6826 bd 81 d 3542 a 419 d 6 해시함수의 결과는 난수처럼 보이는 Byte. String. Buffer 객체 이것을 Hex로 출력하기 위해서는 to. Hex() 함수 이용

해시함수 - Message Digest 11 해시함수의 결과는 난수처럼 보이는 Byte. String. Buffer � � 이것을 Hex로 출력하기 위해서는 to. Hex() 함수 이용 또는 forge. util. bytes. To. Hex 함수 이용 var forge = require('node-forge'); var input. Text = 'The quick brown fox jumps over the lazy dog'; console. log('Input Text: '+input. Text); var md = forge. md 5. create(); md. update(input. Text); console. log('MD 5: '+md. digest(). to. Hex()); > Node digest. js var md = forge. md 5. create(); md. update(input. Text); var result = md. digest(); console. log(result); console. log('MD 5: '+forge. util. bytes. To. Hex(result));

해시함수 - Message Digest 12 digest. js var forge = require('node-forge'); var input. Text = 'The quick brown fox jumps over the lazy dog'; console. log('Input Text: '+input. Text); var md = forge. md 5. create(); md. update(input. Text); console. log('MD 5: '+md. digest(). to. Hex()); var md = forge. md. sha 1. create(); md. update(input. Text); console. log('SHA 1: '+md. digest(). to. Hex()); var md = forge. md. sha 256. create(); md. update(input. Text); console. log('SHA 256: '+md. digest(). to. Hex()); var md = forge. md. sha 384. create(); md. update(input. Text); console. log('SHA 384: '+md. digest(). to. Hex()); var md = forge. md. sha 512. create(); md. update(input. Text); console. log('SHA 512: '+md. digest(). to. Hex()); var md = forge. md. sha 512. sha 256. create(); md. update(input. Text); console. log('SHA 512. SHA 256: '+md. digest(). to. Hex());

해시함수 - Message Digest 13 클라이언트측(브라우저)에서 실행 digest. html <!DOCTYPE html> <head> <meta charset="utf-8"> <title>Digest Test</title> <script src=‘bower_components/forge/dist/forge. min. js’> </script> <script src=‘digest-c. js’></script> </head> <body> </html> console. log document. write 개행명령 추가 digest-c. js var input. Text = 'The quick brown fox jumps over the lazy dog'; document. write('Input Text: '+input. Text+' '); var md = forge. md 5. create(); md. update(input. Text); document. write('MD 5: '+md. digest(). to. Hex()+' '); var md = forge. md. sha 1. create(); md. update(input. Text); document. write('SHA 1: '+md. digest(). to. Hex()+' '); var md = forge. md. sha 256. create(); md. update(input. Text); document. write('SHA 256: '+md. digest(). to. Hex()+' '); var md = forge. md. sha 384. create(); md. update(input. Text); document. write('SHA 384: '+md. digest(). to. Hex()+' '); var md = forge. md. sha 512. create(); md. update(input. Text); document. write('SHA 512: '+md. digest(). to. Hex()+' '); var md = forge. md. sha 512. sha 256. create(); md. update(input. Text); document. write('SHA 512. SHA 256: '+md. digest(). to. Hex()+' ');


MAC 15

Hash와 MAC의 비교 16 Hash MAC



메시지인증 - Hmac 19 API � � Forge. hmac 객체 이용 Create start update digest Start(해시알고리즘, 공유비밀키) Update(입력메시지) var hmac = forge. hmac. create(); hmac. start('sha 1', 'Jefe'); hmac. update('what do ya want for nothing? '); console. log(hmac. digest(). to. Hex()); // output: effcdf 6 ae 5 eb 2 fa 2 d 27416 d 5 f 184 df 9 c 259 a 7 c 79

메시지인증 - Hmac 20 hmac. js var forge = require('node-forge'); var input. Text = 'The quick brown fox jumps over the lazy dog'; var key = 'supersecretkey'; console. log('Input Text: '+input. Text); console. log('Key: '+key); var hmac = forge. hmac. create(); hmac. start('md 5', key); hmac. update(input. Text); console. log('Hmac(md 5): '+hmac. digest(). to. Hex()); var hmac = forge. hmac. create(); hmac. start('sha 1', key); hmac. update(input. Text); console. log('Hmac(sha 1): '+hmac. digest(). to. Hex()); var hmac = forge. hmac. create(); hmac. start('sha 256', key); hmac. update(input. Text); console. log('Hmac(sha 256): '+hmac. digest(). to. Hex()); var hmac = forge. hmac. create(); hmac. start('sha 384', key); hmac. update(input. Text); console. log('Hmac(sha 384): '+hmac. digest(). to. Hex()); var hmac = forge. hmac. create(); hmac. start('sha 512', key); hmac. update(input. Text); console. log('Hmac(sha 512): '+hmac. digest(). to. Hex());



패스워드기반키생성 - PBKDF 2 23 PKCS#5 에 정의됨 � � � password-based key-derivation function forge. pkcs 5. pbkdf 2 객체 제공 사용자입력 패스워드, 난수솔트, 반복횟수, 출력키길이 지정 동기식/비동기식 함수 제공 – 반복횟수가 크면 계산시간이 길어 져 다수 사용자 환경에서는 비동기식 계산 필요 AES의 16 -byte (128비트) 키 생성 사례 // generate a password-based 16 -byte key // note an optional message digest can be passed as the final parameter var salt = forge. random. get. Bytes. Sync(128); var derived. Key = forge. pkcs 5. pbkdf 2('password', salt, num. Iterations, 16); // generate key asynchronously // note an optional message digest can be passed before the callback forge. pkcs 5. pbkdf 2('password', salt, num. Iterations, 16, function(err, derived. Key) { // do something w/derived. Key });

패스워드기반키생성 - PBKDF 2 24 pbkdf 2. js var forge = require('node-forge'); var salt; var num. Iterations = 1000; // generate a password-based 16 -byte key // note an optional message digest can be passed as the final parameter salt = forge. random. get. Bytes. Sync(128); var derived. Key = forge. pkcs 5. pbkdf 2('password', salt, num. Iterations, 16); console. log('Derived key - sync: ', forge. util. bytes. To. Hex(derived. Key)); // generate key asynchronously // note an optional message digest can be passed before the callback salt = forge. random. get. Bytes. Sync(128); forge. pkcs 5. pbkdf 2('password', salt, num. Iterations, 32, function(err, derived. Key) { // do something w/derived. Key 난수 솔트를 이용하므로 console. log('Derived key - async: ', forge. util. bytes. To. Hex(derived. Key)); 동일한 패스워드에 대해 }); 서로 다른 키가 생성됨



소수(prime) 생성 27 var forge = require('node-forge'); // generate a random prime on the main JS thread var bits = 1024; forge. prime. generate. Probable. Prime(bits, function(err, num) { console. log('random prime 1: ', num. to. String(16)); }); // generate a random prime using Web Workers (if available, otherwise // falls back to the main thread) var bits = 1024; var options = { algorithm: { name: 'PRIMEINC', workers: -1 // auto-optimize # of workers } }; forge. prime. generate. Probable. Prime(bits, options, function(err, num) { console. log('random prime 2: ', num. to. String(16)); }); 웹워커를 이용하는 두번째 결과가 먼저 출력됨


난수생성 - PRNG 29 var forge = require('node-forge'); // get some random bytes synchronously var bytes = forge. random. get. Bytes. Sync(32); console. log('PRNG-sync: '+forge. util. bytes. To. Hex(bytes)); // get some random bytes asynchronously forge. random. get. Bytes(32, function(err, bytes) { console. log('PRNG-async: '+forge. util. bytes. To. Hex(bytes)); }); // get some random bytes synchronously var bytes = forge. random. get. Bytes. Sync(64); console. log('PRNG-sync: '+forge. util. bytes. To. Hex(bytes)); // get some random bytes asynchronously forge. random. get. Bytes(64, function(err, bytes) { console. log('PRNG-async: '+forge. util. bytes. To. Hex(bytes)); }); 동기식 난수생성이 먼저 출력됨


인코딩 31 // encode/decode base 64 var encoded = forge. util. encode 64(str); var str = forge. util. decode 64(encoded); Base 64 인코딩/디코딩 // encode/decode UTF-8 var encoded = forge. util. encode. Utf 8(str); var str = forge. util. decode. Utf 8(encoded); // bytes to/from hex var bytes = forge. util. hex. To. Bytes(hex); var hex = forge. util. bytes. To. Hex(bytes); UTF-8 인코딩/디코딩 hex byte hex

인코딩 32 var forge = require('node-forge'); var input. Text = 'The quick brown 한글 테스트'; console. log('Input Text: '+input. Text); console. log(); // encode/decode base 64 var encoded = forge. util. encode 64(input. Text); console. log('Base 64: '+encoded); var str = forge. util. decode 64(encoded); console. log('Recovered: '+str); console. log(); // encode/decode UTF-8 var encoded = forge. util. encode. Utf 8(input. Text); console. log('UTF 8: '+encoded); var str = forge. util. decode. Utf 8(encoded); console. log('Recovered: '+str); console. log(); // bytes to/from hex var hex = '10 e 699642330 d 78 bbc 60834 bfd 338 ff 1497 b 6'; var bytes = forge. util. hex. To. Bytes(hex); console. log('hex. To. Bytes: '+bytes); var hex = forge. util. bytes. To. Hex(bytes); console. log('bytes. To. Hex: '+hex);



대칭키 암호 - Cipher 35 Forge. cipher 객체 이용 암호 알고리즘 � � � 운영모드(modes of operation) � AES : AES-128, AES-192, or AES-256 3 DES : 192비트 DES : 64비트 ECB, CBC, CFB, OFB, CTR, GCM 알고리즘과 운영모드를 함께 선택

대칭키 암호 - Cipher 36 var cipher = forge. cipher. create. Cipher('AES-CBC', key); cipher. start({iv: iv}); cipher. update(forge. util. create. Buffer(some. Bytes)); cipher. finish(); var encrypted = cipher. output; create. Cipher Start Update finish // outputs encrypted hex console. log(encrypted. to. Hex()); var decipher = forge. cipher. create. Decipher('AES-CBC', key); decipher. start({iv: iv}); decipher. update(encrypted); decipher. finish(); // outputs decrypted hex console. log(decipher. output. to. Hex()); create. Decipher Start Update finish

대칭키 암호 - Cipher 37 var forge = require('node-forge'); var input. Text = "Hello world - 헬로월드"; var some. Bytes = forge. util. encode. Utf 8(input. Text); 한글 처리를 위한 UTF-8 인코딩 적용 AES-128 128/8 = console. log('AES-128 -CBC'); var key. Size = 16; // 16 => AES-128, 24 => AES-192, 32 => AES-256 AES-192 192/8 = var key = forge. random. get. Bytes. Sync(key. Size); 난수 키생성 AES-256 256/8 = var iv = forge. random. get. Bytes. Sync(key. Size); DES 64/8 = 8 console. log('- Key: '+forge. util. bytes. To. Hex(key)); console. log('- iv: '+forge. util. bytes. To. Hex(iv)); 3 DES 192/8 = 24 console. log('- Plaintext: '+forge. util. decode. Utf 8(some. Bytes)); var cipher = forge. cipher. create. Cipher('AES-CBC', key); Key : 공유키 cipher. start({iv: iv}); Iv : 초기화 벡터 cipher. update(forge. util. create. Buffer(some. Bytes)); cipher. finish(); var encrypted = cipher. output; forge. util. create. Buffer 이용 // outputs encrypted hex console. log('- Encrypted: '+encrypted. to. Hex()); var decipher = forge. cipher. create. Decipher('AES-CBC', key); decipher. start({iv: iv}); decipher. update(encrypted); decipher. finish(); console. log('- Decrypted: '+decipher. output); console. log(); 16 24 32 출력 암호문은 byte array 화면으로 표시하려면 to. Hex() 함수 이용



RSA 알고리즘 40 1977년 RSA 알고리즘 등장 Shamir Rivest Adleman


공개키암호 - PKI 객체 42 PKI � � RSA 키생성 - forge. pki. rsa RSA 암호화/복호화 – encrypt / decrypt RSAES PKCS#1 v 1. 5 RSAES-OAEP RSA 서명/검증 – sign / verify RSASSA PKCS#1 v 1. 5 RSASSA-PSS RSA key encapsulation – forge. kem � 대칭키 암호화에 사용되는 비밀키를 RSA 암호화로 보호 X. 509 인증서 생성, 이용 – forge. pki

RSA 키생성 43 var forge = require('node-forge'); var rsa = forge. pki. rsa; 키쌍 생성 var keypair = rsa. generate. Key. Pair({bits: 1024, e: 0 x 10001}); 공개키 var public. Key = keypair. public. Key; var private. Key = keypair. private. Key; 개인키 console. log('Public key: n'+forge. pki. public. Key. To. Pem(public. Key)); console. log('Private key: n'+forge. pki. private. Key. To. Pem(private. Key)); forge. pki. public. Key. To. Pem - 공개키를 PEM 형식으로 출력 forge. pki. private. Key. To. Pem - 개인키를 PEM 형식으로 출력

RSA 암호화 44 RSA 암호화/패딩 알고리즘 종류 � � RSAES PKCS#1 v 1. 5 : 기본 PKCS#1 패딩 RSA-OAEP : OAEP 패딩 적용 RSAES-OAEP/SHA-256 : RSAES-OAEP/SHA-256/MGF 1 -SHA-1 :

PKCS 1 Padding 45 PKCS#1 v 1. 5에서의 패딩 방식 난수삽입 DATA 1998년 Bleichenbacher에 의해 취약점 발견 � Adaptive chosen ciphertext attack (적응 선택 암호문 공격)


RSA 암호화 47 var forge = require('node-forge'); var plaintext = "Hello world hello world"; var rsa = forge. pki. rsa; var keypair = rsa. generate. Key. Pair({bits: 1024, e: 0 x 10001}); var public. Key = keypair. public. Key; var private. Key = keypair. private. Key; console. log('Public key: n'+forge. pki. public. Key. To. Pem(public. Key)); console. log('Private key: n'+forge. pki. public. Key. To. Pem(private. Key)); console. log(); // encrypt data with a public key (defaults to RSAES PKCS#1 v 1. 5) console. log('defaults to RSAES PKCS#1 v 1. 5'); var encrypted = public. Key. encrypt(plaintext); console. log('Encrypted: '+forge. util. bytes. To. Hex(encrypted)); // decrypt data with a private key (defaults to RSAES PKCS#1 v 1. 5) var decrypted = private. Key. decrypt(encrypted); console. log('Decrypted: '+decrypted); console. log(); // encrypt data with a public key using RSAES-OAEP console. log('RSA-OAEP'); var encrypted = public. Key. encrypt(plaintext, 'RSA-OAEP'); console. log('Encrypted: '+forge. util. bytes. To. Hex(encrypted)); // decrypt data with a private key using RSAES-OAEP var decrypted = private. Key. decrypt(encrypted, 'RSA-OAEP'); console. log('Decrypted: '+decrypted); console. log(); RSAES PKCS#1 v 1. 5 RSA-OAEP : OAEP 패딩

RSA 암호화 48 // encrypt data with a public key using RSAES-OAEP/SHA-256 console. log('RSAES-OAEP/SHA-256 '); var encrypted = public. Key. encrypt(plaintext, 'RSA-OAEP', { md: forge. md. sha 256. create() }); console. log('Encrypted: '+forge. util. bytes. To. Hex(encrypted)); var decrypted = private. Key. decrypt(encrypted, 'RSA-OAEP', { md: forge. md. sha 256. create() }); console. log('Decrypted: '+decrypted); console. log(); RSAES-OAEP/SHA-256 // encrypt data with a public key using RSAES-OAEP/SHA-256/MGF 1 -SHA-1 // compatible with Java's RSA/ECB/OAEPWith. SHA-256 And. MGF 1 Padding console. log('RSAES-OAEP/SHA-256/MGF 1 -SHA-1 '); MGF: Mask generation function var encrypted = public. Key. encrypt(plaintext, 'RSA-OAEP', { md: forge. md. sha 256. create(), RSAES-OAEP/SHA-256/MGF 1 -SHA-1 mgf 1: { md: forge. md. sha 1. create() } }); console. log('Encrypted: '+forge. util. bytes. To. Hex(encrypted)); var decrypted = private. Key. decrypt(encrypted, 'RSA-OAEP', { md: forge. md. sha 256. create(), mgf 1: { md: forge. md. sha 1. create() } }); console. log('Decrypted: '+decrypted);

RSA 전자서명 49 RSA 전자서명 알고리즘 종류 � � RSASSA PKCS#1 v 1. 5 (default) RSASSA-PSS sign data using RSASSA-PSS where PSS uses a SHA-1 hash, a SHA-1 based masking function MGF 1, and a 20 byte salt


RSA 전자서명 51 var forge = require('node-forge'); var plaintext = "Hello world hello world"; var rsa = forge. pki. rsa; var keypair = rsa. generate. Key. Pair({bits: 1024, e: 0 x 10001}); var public. Key = keypair. public. Key; var private. Key = keypair. private. Key; console. log('Public key: n'+forge. pki. public. Key. To. Pem(public. Key)); console. log('Private key: n'+forge. pki. public. Key. To. Pem(private. Key)); console. log(); // sign data with a private key and output Digest. Info DER-encoded bytes // (defaults to RSASSA PKCS#1 v 1. 5) var md = forge. md. sha 1. create(); md. update(plaintext, 'utf 8'); var signature = private. Key. sign(md); console. log('Signature: '+forge. util. bytes. To. Hex(signature)); // verify data with a public key // (defaults to RSASSA PKCS#1 v 1. 5) var verified = public. Key. verify(md. digest(). bytes(), signature); console. log('Verification: '+verified); console. log(); RSASSA PKCS#1 v 1. 5 // sign data using RSASSA-PSS where PSS uses a SHA-1 hash, a SHA-1 based // masking function MGF 1, and a 20 byte salt var md = forge. md. sha 1. create(); md. update(plaintext, 'utf 8'); var pss = forge. pss. create({ md: forge. md. sha 1. create(), mgf: forge. mgf 1. create(forge. md. sha 1. create()), salt. Length: 20 // optionally pass 'prng' with a custom PRNG implementation // optionalls pass 'salt' with a forge. util. Byte. Buffer w/custom salt }); var signature = private. Key. sign(md, pss); console. log('Signature: '+forge. util. bytes. To. Hex(signature)); // verify RSASSA-PSS signature var pss = forge. pss. create({ md: forge. md. sha 1. create(), mgf: forge. mgf 1. create(forge. md. sha 1. create()), salt. Length: 20 // optionally pass 'prng' with a custom PRNG implementation }); var md = forge. md. sha 1. create(); md. update(plaintext, 'utf 8'); var verified = public. Key. verify(md. digest(). get. Bytes(), signature, pss); console. log('Verification: '+verified); RSASSA-PSS



X. 509 인증서 54 인증서 표준 X. 509, The Directory: Authentication Framework, 1993. 인증서의 구성

PKCS 표준 55 Public Key Cryptography Standards � https: //en. wikipedia. org/wiki/PKCS


인증서 관련 확장자 57 . DER � . CRT � � 인증서 저장에 사용 (Unix 방식) The CRT extension is used for certificates. The certificates may be encoded as binary DER or as ASCII PEM. The CER and CRT extensions are nearly synonymous. . CER � � 인증서 저장에 사용되는 확장자 인증서 저장에 사용 (마이크로소프트 방식) alternate form of. crt (Microsoft Convention) . KEY � � PKCS#8 형식으로 공개키, 개인키 저장에 사용 The keys may be encoded as binary DER or as ASCII PEM


Open. SSL 설치 59 리눅스 환경 � 기본 설치됨 윈도우 환경 � � � http: //slproweb. com/products/Win 32 Open. SSL. html Win 64 Open. SSL v 1. 0. 2 k 다운로드 및 설치 환경변수에 설치 디렉토리 등록, C: Open. SSL-Win 64bin openssl. cfg 파일을 C: Open. SSL-Win 64 폴더에 복사 참고 http: //zero-gravity. tistory. com/239 http: //blog. daum. net/coy 486/15

Open. SSL 사용법 60 RSA 키생성 > openssl genrsa -des 3 -out private. pem 2048




Forge를 이용한 자체서명인증서 생성 64 var var forge = require('node-forge'); fs = require('fs'); pki = forge. pki; rsa = forge. pki. rsa; // generate a keypair and create an X. 509 v 3 certificate var keypair = pki. rsa. generate. Key. Pair(1024); var public. Key = keypair. public. Key; var private. Key = keypair. private. Key; console. log(pki. public. Key. To. Pem(public. Key)); console. log(pki. private. Key. To. Pem(private. Key)); var cert = pki. create. Certificate(); << cert 객체에 필드 정보 입력 >> cert. sign(private. Key);

cert. js cert. set. Subject(attrs); // alternatively set subject from a csr //cert. set. Subject(csr. subject. attributes); var forge = require('node-forge'); cert. set. Issuer(attrs); var fs = require('fs'); cert. set. Extensions([{ var pki = forge. pki; name: 'basic. Constraints', var rsa = forge. pki. rsa; cert. sign(private. Key); c. A: true 65 // generate a keypair and create an X. 509 v 3 certificate }, { // convert a Forge certificate to PEM name: 'key. Usage', var keypair = pki. rsa. generate. Key. Pair(1024); var pem = pki. certificate. To. Pem(cert); key. Cert. Sign: true, var public. Key = keypair. public. Key; console. log(pem); digital. Signature: true, var private. Key = keypair. private. Key; non. Repudiation: true, var verified = cert. verify(cert); key. Encipherment: true, console. log(pki. public. Key. To. Pem(public. Key)); data. Encipherment: true console. log('인증서 검증: '+verified); console. log(pki. private. Key. To. Pem(private. Key)); }, { name: 'ext. Key. Usage', var cert = pki. create. Certificate(); server. Auth: true, cert. public. Key = public. Key; client. Auth: true, // alternatively set public key from a csr code. Signing: true, //cert. public. Key = csr. public. Key; email. Protection: true, cert. serial. Number = '01'; time. Stamping: true cert. validity. not. Before = new Date(); }, { cert. validity. not. After. set. Full. Year(cert. validity. not. Before. get. Full. Year( name: 'ns. Cert. Type', ) + 1); client: true, var attrs = [{ server: true, name: 'common. Name', email: true, value: 'example. org' objsign: true, }, { ssl. CA: true, name: 'country. Name', email. CA: true, value: 'US' obj. CA: true }, { short. Name: 'ST', name: 'subject. Alt. Name', value: 'Virginia' alt. Names: [{ }, { type: 6, // URI name: 'locality. Name', value: 'http: //example. org/webid#me' value: 'Blacksburg' }, { type: 7, // IP name: 'organization. Name', ip: '127. 0. 0. 1' value: 'Test' }] }, { short. Name: 'OU', name: 'subject. Key. Identifier' value: 'Test' }]); }]; 자체서명인증서 생성 예제


인증서 cert 생성 67 주체 정보 attrs 확장영역 var attrs = [{ name: 'common. Name', value: 'example. org' }, { name: 'country. Name', value: 'US' }, { short. Name: 'ST', value: 'Virginia' }, { name: 'locality. Name', value: 'Blacksburg' }, { name: 'organization. Name', value: 'Test' }, { short. Name: 'OU', value: 'Test' }]; cert. set. Extensions([{ name: 'basic. Constraints', c. A: true }, { name: 'key. Usage', key. Cert. Sign: true, digital. Signature: true, non. Repudiation: true, key. Encipherment: true, data. Encipherment: true }, { name: 'ext. Key. Usage', server. Auth: true, client. Auth: true, code. Signing: true, email. Protection: true, time. Stamping: true }, E = sultan@joongbu. ac. kr CN = Byoungcheon Lee OU = Dept. of Information Security O = Joongbu Univ. L = Goyang-si S = Gyeonggi-do C = KR 키 사용 용도 인증기관의 인증서임을 나타냄 { name: 'ns. Cert. Type', client: true, server: true, email: true, 인증서 타입 objsign: true, ssl. CA: true, email. CA: true, obj. CA: true }, { name: 'subject. Alt. Name', alt. Names: [{ type: 6, // URI value: 'http: //example. org/webid#me' }, { type: 7, // IP 주체 별도 정보 ip: '127. 0. 0. 1' }] }, { name: 'subject. Key. Identifier' }]); 주체 키 식별자

주체 정보 지정 방식 68 var attrs = [{ //name: 'common. Name', // CN short. Name: 'CN', value: 'Byoungcheon Lee' }, { //name: 'country. Name', // C short. Name: 'C', value: 'KR' }, { //name: 'state. Or. Province. Name', // ST short. Name: 'ST', value: 'Gyeonggi-do' }, { //name: 'locality. Name', // L short. Name: 'L', value: 'Goyang-si' }, { //name: 'organization. Name', // O short. Name: 'O', value: 'Joongbu Univ. ' }, { //name: 'organizational. Unit. Name', short. Name: 'OU', value: 'Dept. of Information Security' }]; name short. Name common. Name CN country. Name C state. Or. Province. Name ST locality. Name L organization. Name O organizational. Unit. Name OU



인증서에서 공개키 읽어오기 71 사용자의 공개키는 인증서의 필드로 등록되어 있으므로 인증서에서 다음과 같이 간단히 읽어올 수 있음 var public. Key = cert. public. Key; console. log('Extract public key from Certificate: '); console. log(pki. public. Key. To. Pem(cert. public. Key));


인증서/개인키를 파일로 저장하기 73 var forge = require('node-forge'); var fs = require('fs'); var pki = forge. pki; var rsa = forge. pki. rsa; fs 객체 추가 – 파일처리기능 fs는 node. js의 내장객체 // generate a keypair and create an X. 509 v 3 certificate var keypair = pki. rsa. generate. Key. Pair(1024); var public. Key = keypair. public. Key; var private. Key = keypair. private. Key; fs. write. File("public. Key. pem", pki. public. Key. To. Pem(public. Key), function(err) { if(err) { return console. log(err); }}); 공개키 파일 저장 (비동기식) fs. write. File("private. Key. pem", pki. private. Key. To. Pem(private. Key), function(err) { if(err) { return console. log(err); }}); 개인키 파일 저장 (비동기식) fs. write. File("cert. pem", pki. certificate. To. Pem(cert), function(err) { if(err) { return console. log(err); }}); 인증서 파일 저장 (비동기식) fs. write. File. Sync(“cert 1. pem", pki. certificate. To. Pem(cert)); 동기식 개인키 파일 저장 fs. write. File. Sync(“private. Key 1. pem", pki. private. Key. To. Pem(private. Key)); 동기식 인증서 파일 저장

인증서/개인키를 파일에서 읽어오기 74 var fs = require('fs'); console. log("인증서를 파일에서 읽어오기"); fs. read. File('cert. pem', 'utf 8', function (err, data) { if (err) { return console. log(err); 비동기식 읽어오기 } console. log(data); var cert = pki. certificate. From. Pem(data); var pub = cert. public. Key; console. log(pki. public. Key. To. Pem(cert. public. Key)); }); var var cert. Pem = fs. read. File. Sync(‘cert. pem', 'utf 8'); private. Key. Pem = fs. read. File. Sync(‘private. Key. pem', 'utf 8'); cert = pki. certificate. From. Pem(cert. Pem); private. Key = pki. private. Key. From. Pem(private. Key. Pem); 동기식 읽어오기


PKCS#8 API 76 개인키객체 (private. Key) private. Key. To. Pem private. Key. From. Pem private. Key. To. Asn 1 private. Key. From. Asn 1 asn. 1개인키 (rsa. Private. Key) 암호화되지 않은 개인키 Pem개인키 (pem) private. Key. Info. To. Pem wrap. Rsa. Private. Key PKCS#8 ASN. 1 (private. Key. Info) 파일에서 개인키 읽어오고 복구하기 encrypt. Private. Key. Info (password) decrypt. Private. Key. Info (password) 암호화된 개인키를 파일로 저장하기 Encrypted. Private. Key. Info encrypted. Private. Key. To. Pem encrypted. Private. Key. From. Pem Encrypted. Pem 패스워드 암호화하여 저장한 개인키

PKCS#8 API 77 개인키객체 (private. Key) set. Rsa. Public. Key 공개키객체 (public. Key) 개인키 객체에는 공개키 정보를 가지고 있음 개인키로부터 공개키를 추출할 수 있음 encrypt. Rsa. Private. Key (password) decrypt. Rsa. Private. Key (password) Encrypted. Pem 패스워드 암호화하여 저장한 개인키

var var 78 forge = require('node-forge'); plaintext = "Hello world hello world"; pki = forge. pki; rsa = forge. pki. rsa; var var var keypair = rsa. generate. Key. Pair({bits: 1024, e: 0 x 10001}); public. Key = keypair. public. Key; private. Key = keypair. private. Key; pub. Pem = forge. pki. public. Key. To. Pem(public. Key); priv. Pem = forge. pki. private. Key. To. Pem(private. Key); PKCS#8 test – full API console. log('Public key: n'+pub. Pem); console. log('Private key: n'+priv. Pem); console. log(); // PEM에서 개인키 읽어오기 // decrypts an ASN. 1 Encrypted. Private. Key. Info var private. Key 1 = pki. private. Key. From. Pem(priv. Pem); var private. Key. Info 1 = pki. decrypt. Private. Key. Info( console. log('Pem to Private key: n'+pki. private. Key. To. Pem(private. Key 1)); encrypted. Private. Key. Info, 'password'); console. log('Private key Info (enc/dec): n'+pki. private. Key. Info. To. Pem(private. Key. Info 1)); // 개인키를 ASN. 1으로 출력 var priv. Asn 1 = pki. private. Key. To. Asn 1(private. Key); // converts an Encrypted. Private. Key. Info to PEM // convert an ASN. 1 Private. Key. Info or RSAPrivate. Key to a Forgevar private pem key = pki. encrypted. Private. Key. To. Pem(encrypted. Private. Key. Info); var private. Key 2 = pki. private. Key. From. Asn 1(priv. Asn 1); console. log('Encrypted. Private. Key. Info 1: n'+pem); console. log('ASN. 1 to Private key: n'+pki. private. Key. To. Pem(private. Key 2)); // converts a PEM-encoded Encrypted. Private. Key. Info to ASN. 1 format // ASN. 1 개인키를 Private. Key. Info로 wrapping한 후에 pem으로 변환 var encrypted. Private. Key. Info = pki. encrypted. Private. Key. From. Pem(pem); // wrap an RSAPrivate. Key ASN. 1 object in a PKCS#8 ASN. 1 Private. Key. Info var private. Key. Info = pki. wrap. Rsa. Private. Key(priv. Asn 1); // wraps and encrypts a Forge private key and outputs it in PEM format // convert a PKCS#8 ASN. 1 Private. Key. Info to PEM var pem = pki. encrypt. Rsa. Private. Key(private. Key, 'password'); var pem = pki. private. Key. Info. To. Pem(private. Key. Info); console. log('Encrypted. Private. Key. Info 2: n'+pem); console. log('Private key Info: n'+pem); // decrypts a PEM-formatted, encrypted private key // Private. Key. Info를 패스워드 암호화/복호화 var private. Key 2 = pki. decrypt. Rsa. Private. Key(pem, 'password'); // encrypts a Private. Key. Info and outputs an Encrypted. Private. Key. Info console. log('Pem to Private key 2: n'+pki. private. Key. To. Pem(private. Key 2)); var encrypted. Private. Key. Info = pki. encrypt. Private. Key. Info( private. Key. Info, 'password', { // sets an RSA public key from a private key algorithm: 'aes 256', // 'aes 128', 'aes 192', 'aes 256', '3 des' var public. Key 1 = pki. set. Rsa. Public. Key(private. Key. n, private. Key. e); }); console. log('Public key from Private key: n'+pki. public. Key. To. Pem(public. Key 1));

PKCS#8 test – short API 79 var var forge = require('node-forge'); plaintext = "Hello world hello world"; pki = forge. pki; rsa = forge. pki. rsa; var keypair = rsa. generate. Key. Pair({bits: 1024, e: 0 x 10001}); var public. Key = keypair. public. Key; var private. Key = keypair. private. Key; console. log('Public key: n'+forge. pki. public. Key. To. Pem(public. Key)); console. log('Private key: n'+forge. pki. private. Key. To. Pem(private. Key)); // wraps and encrypts a Forge private key and outputs it in PEM format var pem = pki. encrypt. Rsa. Private. Key(private. Key, 'password'); console. log('Encrypted. Private. Key. Info(password): n'+pem); F: Applied. Cryptoforge>node pkcs 8 -s. js Public key: -----BEGIN PUBLIC KEY----MIGf. MA 0 GCSq. GSIb 3 DQEBAQUAA 4 GNADCBi. QKBg. QCJf. Gb. U 0 B 7 qkbq 33 uksrwa. Hs 0 Wh l. Afz. RTCJq 6 Lb. OOVW 8 SRzkvj 83 Xaeu 9 o. SSYo. Ir. S 80 z 4 GRDjzetzrh. AA 2 q. M 8 N 53 w. Cz Zyqiw 9/51 zdo 1 IBin. Q/q 5 RGA 83 QPCENKZy 5 TWV 6 Mi. FOb. D 9 Qwd. Gq. Tqw. PPviy 5 z 1 a. Y Yl 9 Gi 6 f 5 PDfoc 1 b 8 r. QIDAQAB -----END PUBLIC KEY----- 공개키 Private key: -----BEGIN RSA PRIVATE KEY----MIICXAIBAAKBg. QCJf. Gb. U 0 B 7 qkbq 33 uksrwa. Hs 0 Whl. Afz. RTCJq 6 Lb. OOVW 8 SRzkvj 8 3 Xaeu 9 o. SSYo. Ir. S 80 z 4 GRDjzetzrh. AA 2 q. M 8 N 53 w. Cz. Zyqiw 9/51 zdo 1 IBin. Q/q 5 RGA 83 QPCENKZy 5 TWV 6 Mi. FOb. D 9 Qwd. Gq. Tqw. PPviy 5 z 1 a. YYl 9 Gi 6 f 5 PDfoc 1 b 8 r. QIDAQAB Ao. GAPy. Yqv. Vk. Suj 9 Reh 8 j. Dukdo. Lr. RIt. Qxiq. Wf. E 70 IQp. Uxkeu. VCJjb. UJo. QX/x 8 v 6 WT h 0 S 0 y. Bb/tjb. J 8 qp. Kmwp. BPIom. IGnbnk. Wf 0 qis 0 CBvmno+9 hd 0 MVMv 7 f 1 EZb 34 Ud. Nd MLXKggol. Yl 6 K 0 YWAMfd. Wao. Pt. LA 582 a. TOl. A 3 PHURf. LKi 18 YECQQC 75 x. Vcn. Mk 5 n. F 2 Y m. SMWn 8 z. Ga 7 YRXh. WDNZM 9 qsik. V 503 f. Fnq/l. Cm. Q 4 d. KOq 2 ksl. Ts 7 Ci. AWJ 2 zj 9 pp. Jqh. U M 1 IRhxr 9 Ak. EAu 0/XJXYWBO+y 7 Hwgv 69 b 3 ml 8 N+Olk. IGt. SLLf. T/gqzfx. TIUIzzukf iygp/veb. N 2 A 8+00 JAdhy. X 60 Nuc 0 Yi. OBPc. QJAZpaq 1 g 6 P 2 p. Fhl. H//ZUn. H 3 ol. ONTs 9 2 Y 41 np. SQy. RFAt 9 t/q. Ep. DNBNo. WQGibmoi 7 dud 3 T 0 El. NW 0 d. HZzrsz 6 QLGX 7 QJAJQe. X p. NQ/bi. Jk 4 NN 5 Nev. Y 4 ZNA 91 u. Ns 4+v. Thvugc. Sx 0 Z 78 YCr. SSyl. TDx. OVmc 4 h. ZUUl. SRjl mv. PLSJb. Ri 9 W 77/NIQQJBAJ 1 x 7 rowv. Kdb. SQ 9 NKO 32 s. XJnpr. Zl. KUS 7 ws 6 m. Vxk. FAQ 6 C r/b 0 r. EP 9 Z 1 e. YS 0 I 659 uf. Js. Px. Tk+9 z. ZAd 0 K 5 YKe 9 h. Tt. I= -----END RSA PRIVATE KEY----- 개인키 Encrypted. Private. Key. Info(password): -----BEGIN ENCRYPTED PRIVATE KEY----MIICzz. BJBgkqhki. G 9 w 0 BBQ 0 w. PDAb. Bgkqhki. G 9 w 0 BBQww. Dg. QIHm. L 3 y. HFj 0 Hk. CAgg. A MB 0 GCWCGSAFl. Aw. QBAg. QQ 5 H 2 i. BFh. Sjcn. Jqsok. Jfxa. HQSCAo. Dwth. GJLf. Ql 95 b. Ox. LU 7 k. W 2 KBMOTDEt. Gmwe. Lwx. TO 9/Ono 0 yrw 9 Rz. LMEo. EOo 9 Bhl. CHv. Ml 5 ya 2 Ap 9 i. UQB 5 t 9 tv o. Rh. Hf. SHqch+v. QXd. Vc 79 ebp. ETrj 32 k. NKVn. Bs. WIn. Rdc. UMef. K 4 l/M+o. IBxl. HQOX+QXd m. AHd. ALg 2 mx 077+a. Cb 49 q 0 a. Ipj. Dp. XOLM/m. Fktr. Fm. I 5 d. GNe. Yu. NT 0 x 65 Zaynixf 7 r. Js 4 Ib 0 m. Xr+yujr 9 d. AN 0 G 6+O 3 fs. JWHRL 5 VUKJ 32 Ru. Xkn. Rrig 0 i 1 BPRA 7 HUv. Nsz. UQx. Zj r. ZL 68 Mqn. TOnq. Ft. Xnu. WOv 93 Tr. Bu. DZUo. PS 00 D 2/q. Qh. Rym 9 f. Ed. VV 48 s 9 d. Hm. Q 4+d 7 Bm 2 F 4 q. Rak/fu. Rm. ZOlir. Y 3 eb. KFtf. KUkx+9 fv. AS 6 LUq. EWK 0 ftdmu. MCnw. JUce. Waz 4 RJw. UE ah. Skas 7 Ud/b. H 9 jesvu 8 BEU 17 juwf 7 v+m++Bbjw 8 G 0740 K 2 rd. Bz. H 3 W 0 ssjld 4 C 1 P 1 g 5 m. Xnbmd. Ns 6661 FW 2 F 79 d. G/t. ZUvv 2 bv. EGZxzzp. VQRULHA 8 Hf 1 NOHPX 05 Ns. F/v 6 IX XUjy. Jy. XRl 8 x. D 151 g+p. Vvruj. Lv. YBLt. JTd 4 Tm 3 a 7 Yq. FJ 4 NM 6 dxrr/r. BPP 1 SMd. Aydd. A mnmsv. SUje. Nh. Kz 2 z. KDob. OKWKBMAlf 5 n. XOm. FE 0+g 5 ciyfhu. Vg. KGLCGPHk. MNlm+fh 0 F j. MCUED 3 Llfr. VQKNh. MKdkv. Ljkl 2 Nkl. FPt 2 Gjv. S 1 s+Yk. H 1 ks. Xmm. Dq+Ie 87 v. BKU 9 Bhd 93 Kpk+k. As. GBk. DK 07 DDz. TYv. RAJJ 1 BNl 2 t. G 2 x/Oaj 5 b. Wk. Eli. X 4 QOw. NKz. QZurvx. Xtdn E 2 j. PVAGESz 3 vvo. Drg. WSKF/TGRkn. RO 1 o. S 2 fxsl. Ux/qeo 5 Rs 8 Usu. QSUslxb. MK 2 a. FIK 7 c. OM -----END ENCRYPTED PRIVATE KEY----- 암호화된 개인키 Decrypted Private key (password): // decrypts a PEM-formatted, encrypted private key -----BEGIN RSA PRIVATE KEY----MIICXAIBAAKBg. QCJf. Gb. U 0 B 7 qkbq 33 uksrwa. Hs 0 Whl. Afz. RTCJq 6 Lb. OOVW 8 SRzkvj 8 var private. Key 1 = pki. decrypt. Rsa. Private. Key(pem, 'password'); 3 Xaeu 9 o. SSYo. Ir. S 80 z 4 GRDjzetzrh. AA 2 q. M 8 N 53 w. Cz. Zyqiw 9/51 zdo 1 IBin. Q/q 5 RGA 83 QPCENKZy 5 TWV 6 Mi. FOb. D 9 Qwd. Gq. Tqw. PPviy 5 z 1 a. YYl 9 Gi 6 f 5 PDfoc 1 b 8 r. QIDAQAB console. log('Decrypted Private key (password): n'+pki. private. Key. To. Pem(private. Key 1)); Ao. GAPy. Yqv. Vk. Suj 9 Reh 8 j. Dukdo. Lr. RIt. Qxiq. Wf. E 70 IQp. Uxkeu. VCJjb. UJo. QX/x 8 v 6 WT // sets an RSA public key from a private key var public. Key 1 = pki. set. Rsa. Public. Key(private. Key. n, private. Key. e); console. log('Public key from Private key: n'+pki. public. Key. To. Pem(public. Key 1)); h 0 S 0 y. Bb/tjb. J 8 qp. Kmwp. BPIom. IGnbnk. Wf 0 qis 0 CBvmno+9 hd 0 MVMv 7 f 1 EZb 34 Ud. Nd MLXKggol. Yl 6 K 0 YWAMfd. Wao. Pt. LA 582 a. TOl. A 3 PHURf. LKi 18 YECQQC 75 x. Vcn. Mk 5 n. F 2 Y m. SMWn 8 z. Ga 7 YRXh. WDNZM 9 qsik. V 503 f. Fnq/l. Cm. Q 4 d. KOq 2 ksl. Ts 7 Ci. AWJ 2 zj 9 pp. Jqh. U M 1 IRhxr 9 Ak. EAu 0/XJXYWBO+y 7 Hwgv 69 b 3 ml 8 N+Olk. IGt. SLLf. T/gqzfx. TIUIzzukf iygp/veb. N 2 A 8+00 JAdhy. X 60 Nuc 0 Yi. OBPc. QJAZpaq 1 g 6 P 2 p. Fhl. H//ZUn. H 3 ol. ONTs 9 2 Y 41 np. SQy. RFAt 9 t/q. Ep. DNBNo. WQGibmoi 7 dud 3 T 0 El. NW 0 d. HZzrsz 6 QLGX 7 QJAJQe. X p. NQ/bi. Jk 4 NN 5 Nev. Y 4 ZNA 91 u. Ns 4+v. Thvugc. Sx 0 Z 78 YCr. SSyl. TDx. OVmc 4 h. ZUUl. SRjl mv. PLSJb. Ri 9 W 77/NIQQJBAJ 1 x 7 rowv. Kdb. SQ 9 NKO 32 s. XJnpr. Zl. KUS 7 ws 6 m. Vxk. FAQ 6 C r/b 0 r. EP 9 Z 1 e. YS 0 I 659 uf. Js. Px. Tk+9 z. ZAd 0 K 5 YKe 9 h. Tt. I= -----END RSA PRIVATE KEY----- 복구된 개인키 Public key from Private key: -----BEGIN PUBLIC KEY----MIGf. MA 0 GCSq. GSIb 3 DQEBAQUAA 4 GNADCBi. QKBg. QCJf. Gb. U 0 B 7 qkbq 33 uksrwa. Hs 0 Wh l. Afz. RTCJq 6 Lb. OOVW 8 SRzkvj 83 Xaeu 9 o. SSYo. Ir. S 80 z 4 GRDjzetzrh. AA 2 q. M 8 N 53 w. Cz Zyqiw 9/51 zdo 1 IBin. Q/q 5 RGA 83 QPCENKZy 5 TWV 6 Mi. FOb. D 9 Qwd. Gq. Tqw. PPviy 5 z 1 a. Y Yl 9 Gi 6 f 5 PDfoc 1 b 8 r. QIDAQAB -----END PUBLIC KEY----- 개인키로부터 복구된 공개키


인증기관에서 자체서명인증서 생성 81 var forge = require('node-forge'); var fs = require('fs'); var pki = forge. pki; cacert. js // 1. CA 인증서 생성 // generate a keypair and create an X. 509 v 3 certificate var ca. Keys = pki. rsa. generate. Key. Pair(2048); var ca. Cert = pki. create. Certificate(); // CA 개인키 파일 저장 console. log(pki. private. Key. To. Pem(ca. Keys. private. Key)); fs. write. File. Sync("ca. Private. Key. pem", pki. private. Key. To. Pem(ca. Keys. private. Key)); console. log('CA개인키 저장 - ca. Private. Key. pem n'); ca. Cert. public. Key = ca. Keys. public. Key; ca. Cert. serial. Number = '01'; ca. Cert. validity. not. Before = new Date(); ca. Cert. validity. not. After. set. Full. Year(ca. Cert. validity. not. Before. get. Full. Year() + 1); var ca. Attrs = [{ //name: 'common. Name', // CN short. Name: 'CN', value: 'Byoungcheon Lee' }, { //name: 'country. Name', // C short. Name: 'C', value: 'KR' }, { //name: 'state. Or. Province. Name', // ST short. Name: 'ST', value: 'Gyeonggi-do' }, { //name: 'locality. Name', // L short. Name: 'L', value: 'Goyang-si' }, { //name: 'organization. Name', // O short. Name: 'O', value: 'Joongbu Univ. ' }, { //name: 'organizational. Unit. Name', short. Name: 'OU', value: 'Dept. of Information Security' }]; ca. Cert. set. Subject(ca. Attrs); ca. Cert. set. Issuer(ca. Attrs); ca. Cert. set. Extensions([{ name: 'basic. Constraints', c. A: true }, { name: 'key. Usage', key. Cert. Sign: true, digital. Signature: true, non. Repudiation: true, key. Encipherment: true, data. Encipherment: true }, { name: 'ext. Key. Usage', server. Auth: true, client. Auth: true, code. Signing: true, email. Protection: true, time. Stamping: true }, { name: 'ns. Cert. Type', client: true, server: true, email: true, objsign: true, ssl. CA: true, email. CA: true, obj. CA: true }, { name: 'subject. Alt. Name', alt. Names: [{ type: 6, // URI value: 'http: //example. org/webid#me' }, { type: 7, // IP ip: '127. 0. 0. 1' }] }, { name: 'subject. Key. Identifier' }]); 개인키 파일 저장 - ca. Private. Key. pem 인증서 파일 저장 - ca. Cert. pem // self-sign certificate ca. Cert. sign(ca. Keys. private. Key); console. log('CA 자체서명인증서 생성'); console. log(pki. certificate. To. Pem(ca. Cert)); var verified = ca. Cert. verify(ca. Cert); console. log('CA인증서 생성 후 검증: '+verified); console. log(); // CA 인증서 저장 fs. write. File. Sync("ca. Cert. pem", pki. certificate. To. Pem(ca. Cert)); console. log('CA인증서 저장 - ca. Cert. pem');

인증서에서 필드 정보 읽어오기 82 console. log('Serial number: '+ca. Cert. serial. Number); console. log('validity-not. Before: '+ca. Cert. validity. not. Before); console. log('validity-not. After: '+ca. Cert. validity. not. After); console. log('Common Name: '+ca. Cert. subject. get. Field('CN'). value); console. log('Organization: '+ ca. Cert. subject. get. Field('O'). value); console. log('Organization Unit: '+ ca. Cert. subject. get. Field('OU'). value); console. log('Locality Name: '+ca. Cert. subject. get. Field('L'). value); console. log('State Name: '+ca. Cert. subject. get. Field('ST'). value); console. log('Country Name: '+ca. Cert. subject. get. Field('C'). value);

개인 사용자에게 인증서 발급 (1/2) 83 var forge = require('node-forge'); var fs = require('fs'); var pki = forge. pki; cert. js // CA 개인키와 인증서를 파일에서 읽어오기 var ca. Cert. Pem = fs. read. File. Sync('ca. Cert. pem', 'utf 8'); var ca. Private. Key. Pem = fs. read. File. Sync('ca. Private. Key. pem', 'utf 8'); var ca. Cert = pki. certificate. From. Pem(ca. Cert. Pem); var ca. Private. Key = pki. private. Key. From. Pem(ca. Private. Key. Pem); var verified = ca. Cert. verify(ca. Cert); console. log('CA인증서 읽어와서 검증: '+verified); // ---------------// 사용자 인증서 생성 및 검증 (CA인증서로 서명) var keys = pki. rsa. generate. Key. Pair(2048); var cert = pki. create. Certificate(); // 사용자 개인키 파일 저장 console. log(pki. private. Key. To. Pem(keys. private. Key)); fs. write. File. Sync("user. Private. Key. pem", pki. private. Key. To. Pem(keys. private. Key)); console. log('사용자 개인키 저장 - user. Private. Key. pem n'); cert. public. Key = keys. public. Key; cert. serial. Number = '01'; cert. validity. not. Before = new Date(); cert. validity. not. After. set. Full. Year(cert. validity. not. Before. get. Full. Year() + 1); 개인키 파일 저장 - user. Private. Key. pem var attrs = [{ name: 'common. Name', // short. Name: 'CN', value: 'example. org' }, { name: 'country. Name', // short. Name: 'C', value: 'US' }, { short. Name: 'ST', value: 'Virginia' }, { name: 'locality. Name', // short. Name: 'L', value: 'Blacksburg' }, { name: 'organization. Name', // short. Name: 'O', value: 'Test' }, { short. Name: 'OU', value: 'Test' }]; cert. set. Subject(attrs); 사용자 subject 정보 입력 뒤쪽에 내용 연결

개인 사용자에게 인증서 발급 (2/2) 84 var ca. Attrs = [{ name: 'common. Name', // short. Name: 'CN', value: ca. Cert. subject. get. Field('CN'). value }, { name: 'country. Name', // short. Name: 'C', value: ca. Cert. subject. get. Field('C'). value }, { name: 'state. Or. Province. Name', // short. Name: 'ST', value: ca. Cert. subject. get. Field('ST'). value }, { name: 'locality. Name', // short. Name: 'L', value: ca. Cert. subject. get. Field('L'). value }, { name: 'organization. Name', // short. Name: 'O', value: ca. Cert. subject. get. Field('O'). value }, { name: 'organizational. Unit. Name', // short. Name: 'OU', value: ca. Cert. subject. get. Field('OU'). value }]; cert. set. Issuer(ca. Attrs); 인증기관 issuer 정보 입력 - ca. Cert에서 읽어온 정보를 입력 - 정보가 다를 경우 사용자인증서 검증시 에러 발생 확장영역 정보 입력 cert. set. Extensions([{ name: 'basic. Constraints', c. A: true }, { name: 'key. Usage', key. Cert. Sign: true, digital. Signature: true, non. Repudiation: true, key. Encipherment: true, data. Encipherment: true }, { name: 'ext. Key. Usage', server. Auth: true, client. Auth: true, code. Signing: true, email. Protection: true, time. Stamping: true }, { name: 'ns. Cert. Type', client: true, server: true, email: true, objsign: true, ssl. CA: true, email. CA: true, obj. CA: true }, { name: 'subject. Alt. Name', alt. Names: [{ type: 6, // URI value: 'http: //example. org/webid#me' }, { type: 7, // IP ip: '127. 0. 0. 1' }] }, { name: 'subject. Key. Identifier' }]); // 사용자 인증서 생성 cert. sign(ca. Private. Key); // CA 개인키로 서명 console. log('사용자 인증서 생성'); console. log(pki. certificate. To. Pem(cert)); // 사용자 인증서 검증 var verified = ca. Cert. verify(cert); console. log('사용자 인증서 검증: '+verified); // 사용자 인증서 저장 fs. write. File. Sync("cert. pem", pki. certificate. To. Pem(cert)); console. log('사용자 인증서 저장 - cert. pem'); 인증서 파일 저장 - cert. pem

인증서 검증 85 // 사용자 인증서 검증 var verified = ca. Cert. verify(cert); console. log('사용자 인증서 검증: '+verified); CA인증서. verify(사용자인증서) set. Issuer 함수의 ca. Attrs 정보가 CA인증서 정보와 다를 경우 사용자인증서 검증시 에러 발생 F: Applied. Cryptoforgenode_modulesnode-forgelibx 509. js: 1070 throw error; ^ Error: The parent certificate did not issue the given child certificate; the child certificate's issuer does not match the parent's subject. at Object. cert. verify (F: Applied. Cryptoforgenode_modulesnode-forgelibx 509. js: 1065: 19) at Object. <anonymous> (F: Applied. Cryptoforgecert. js: 112: 23) at Module. _compile (module. js: 569: 30) at Object. Module. _extensions. . js (module. js: 580: 10) at Module. load (module. js: 503: 32) at try. Module. Load (module. js: 466: 12) at Function. Module. _load (module. js: 458: 3) at Function. Module. run. Main (module. js: 605: 10) at startup (bootstrap_node. js: 158: 16) at bootstrap_node. js: 575: 3
