Download presentation
Presentation is loading. Please wait.
1
암호학 응용 Applied cryptography 2017. 9.
중부대학교 정보보호학과 이병천 교수
2
차례 1. 강의 개요 2. Javascript Cryptography 3. Node.js crypto 4. Crypto-js
5. Example 1 – Chatting 6. Forge 7. Certificate
3
7. 인증서 활용 인증기관 운영 - 인증서 발급 - 인증서, 개인키의 파일 저장, 파일에서 읽어오기
- 인증서, 개인키의 로컬스토리지 저장, 활용
4
파일생성, 메뉴 추가 Forgecert.html
<!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li><a href="index.html">Home <span class="sr-only">(current)</span></a></li> <li><a href="about.html">About</a></li> <li><a href="chat.html">Chatting</a></li> <li><a href="cryptojs.html">Crypto-js</a></li> <li><a href="forge.html">Forge</a></li> <li><a href="forgersa.html">Forge-RSA</a></li> <li class="active"><a href="forgecert.html">Forge-Cert</a></li> </ul> </div><!-- /.navbar-collapse --> 중략 <script src="forgecert.js"></script>
5
인증서 발급 신청 Forgecert.html - UI <h1>인증서 발급 신청</h1>
<div class="form-group"> <label for="certKeySize">RSA KeySize:</label> <select class="form-control" id="certKeySize"> <option value="1">1024</option> <option value="2" selected>2048</option> </select> </div> Country Name (국가): <input type="text" id="country" class="form-control"> State or Province Name (지역): <input type="text" id="state" class="form-control"> Locality Name (도시): <input type="text" id="locality" class="form-control"> Organization Name (기관): <input type="text" id="organization" class="form-control"> Organization Unit Name (부서): <input type="text" id="orgUnit" class="form-control"> Common Name (이름): <input type="text" id="common" class="form-control"> Address (이메일): <input type="text" id=" " class="form-control"> <br> <button id="certButton" class="btn btn-danger">인증서 발급 요청</button>
6
인증서 발급 신청 Forgecert.js – Client JS 요소이름 변수 생성 // Get Elements
var certKeySize = element('certKeySize'); var country = element('country'); var state = element('state'); var locality = element('locality'); var organization = element('organization'); var orgUnit = element('orgUnit'); var common = element('common'); var = element(' '); var userPub = element('userPub'); var userPriv = element('userPriv'); var userCert = element('userCert'); var caCert = element('caCert'); var verify = element('verify'); var fileSaveButton = element('fileSaveButton'); var lsSaveButton = element('lsSaveButton'); var readPrivateKey = element('readPrivateKey'); var readCert = element('readCert'); var readCaCert = element('readCaCert'); var userPriv1 = element('userPriv1'); var userCert1 = element('userCert1'); var caCert1 = element('caCert1'); var lsReadButton = element('lsReadButton'); var userPriv2 = element('userPriv2'); var userCert2 = element('userCert2'); var caCert2 = element('caCert2'); var verify2 = element('verify2'); var lsClearButton = element('lsClearButton');
7
인증서 발급 신청 Forgecert.js – Client JS var pki = forge.pki;
// Connect to socket.io var socket = io.connect(' //var socket = io.connect(' // Check for connection if(socket !== undefined){ console.log('Connected to socket...'); var publicKeyPem, privateKeyPem; var userCertPem, caCertPem; // 인증서 발급 요청 certButton.addEventListener('click', function(){ var optionSize = certKeySize.options[certKeySize.selectedIndex].value; var size; if (optionSize == "1") size = 1024; else if (optionSize == "2") size = 2048; var keypair = pki.rsa.generateKeyPair(size); var publicKey = keypair.publicKey; var privateKey = keypair.privateKey; privateKeyPem = pki.privateKeyToPem(privateKey); publicKeyPem = pki.publicKeyToPem(publicKey); userPub.value = publicKeyPem; userPriv.value = privateKeyPem; var req = { country: country.value, state: state.value, locality: locality.value, organization: organization.value, orgUnit: orgUnit.value, common: common.value, .value, userPub: userPub.value } socket.emit('certReq', req); }); Forgecert.js – Client JS // 인증서 발급 응답 socket.on('certRes', function(data){ userCert.value = data.cert; caCert.value = data.caCert; userCertPem = data.cert; caCertPem = data.caCert; var uCert = pki.certificateFromPem(data.cert); var cCert = pki.certificateFromPem(data.caCert); var verified = cCert.verify(uCert); verify.value = verified; });
8
서버 운영을 위한 준비 프로젝트 폴더로 이동 서버측 패키지 설치 클라이언트측 패키지 설치
> 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
인증기관에서 사용할 자체서명인증서 생성 Cacert.js 개인키 파일 저장 - caPrivateKey.pem
var forge = require('node-forge'); var fs = require('fs'); var pki = forge.pki; // 1. CA 인증서 생성 // generate a keypair and create an X.509v3 certificate var caKeys = pki.rsa.generateKeyPair(2048); var caCert = pki.createCertificate(); // CA 개인키 파일 저장 console.log(pki.privateKeyToPem(caKeys.privateKey)); fs.writeFileSync("caPrivateKey.pem", pki.privateKeyToPem(caKeys.privateKey)); console.log('CA개인키 저장 - caPrivateKey.pem \n'); caCert.publicKey = caKeys.publicKey; caCert.serialNumber = '01'; caCert.validity.notBefore = new Date(); caCert.validity.notAfter = new Date(); caCert.validity.notAfter.setFullYear(caCert.validity.notBefore.getFullYear() + 1); var caAttrs = [{ //name: 'commonName', // CN shortName: 'CN', value: 'Byoungcheon Lee' }, { //name: 'countryName', // C shortName: 'C', value: 'KR' //name: 'stateOrProvinceName', // ST shortName: 'ST', value: 'Gyeonggi-do' //name: 'localityName', // L shortName: 'L', value: 'Goyang-si' //name: 'organizationName', // O shortName: 'O', value: 'Joongbu Univ.' //name: 'organizationalUnitName', shortName: 'OU', value: 'Dept. of Information Security' }]; caCert.setSubject(caAttrs); caCert.setIssuer(caAttrs); caCert.setExtensions([{ name: 'basicConstraints', cA: true }, { name: 'keyUsage', keyCertSign: true, digitalSignature: true, nonRepudiation: true, keyEncipherment: true, dataEncipherment: true name: 'extKeyUsage', serverAuth: true, clientAuth: true, codeSigning: true, Protection: true, timeStamping: true name: 'nsCertType', client: true, server: true, true, objsign: true, sslCA: true, CA: true, objCA: true name: 'subjectAltName', altNames: [{ type: 6, // URI value: ' type: 7, // IP ip: ' ' }] name: 'subjectKeyIdentifier' }]); // self-sign certificate caCert.sign(caKeys.privateKey); console.log('CA 자체서명인증서 생성'); console.log(pki.certificateToPem(caCert)); var verified = caCert.verify(caCert); console.log('CA인증서 생성 후 검증: '+verified); console.log(); // CA 인증서 저장 fs.writeFileSync("caCert.pem", pki.certificateToPem(caCert)); console.log('CA인증서 저장 - caCert.pem'); 개인키 파일 저장 - caPrivateKey.pem 인증서 파일 저장 - caCert.pem
10
Server.js 파일 준비 Server.js // 파일 앞부분에 다음 내용 추가
const fs = require('fs'); const forge = require('node-forge'); const pki = forge.pki; const caCertPem = fs.readFileSync('caCert.pem', 'utf8'); const caPrivateKeyPem = fs.readFileSync('caPrivateKey.pem', 'utf8'); const caCert = pki.certificateFromPem(caCertPem); const caPrivateKey = pki.privateKeyFromPem(caPrivateKeyPem); forge, pki 객체 생성 CA의 개인키, 인증서를 파일에서 읽어옴 (파일이 같은 폴더에 있는지 확인)
11
서버의 인증서 발급 Server.js 사용자인증서와 Ca인증서를 리턴 cert.setExtensions([{
name: 'basicConstraints', cA: true }, { name: 'keyUsage', keyCertSign: true, digitalSignature: true, nonRepudiation: true, keyEncipherment: true, dataEncipherment: true name: 'extKeyUsage', serverAuth: true, clientAuth: true, codeSigning: true, Protection: true, timeStamping: true name: 'nsCertType', client: true, server: true, true, objsign: true, sslCA: true, CA: true, objCA: true name: 'subjectAltName', altNames: [{ type: 6, // URI value: ' type: 7, // IP ip: ' ' }] name: 'subjectKeyIdentifier' }]); 서버의 인증서 발급 Server.js socket.on('certReq', function(req){ var pki = forge.pki; var rsa = forge.pki.rsa; var cert = pki.createCertificate(); cert.publicKey = pki.publicKeyFromPem(req.userPub); cert.serialNumber = '01'; cert.validity.notBefore = new Date(); cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1); var userAttrs = [{ name: 'commonName', value: req.common }, { name: 'countryName', value: req.country shortName: 'ST', value: req.state name: 'localityName', value: req.locality name: 'organizationName', value: req.organization shortName: 'OU', value: req.orgUnit }]; cert.setSubject(userAttrs); cert.sign(caPrivateKey); var result = { cert: pki.certificateToPem(cert), caCert: pki.certificateToPem(caCert) }; socket.emit('certRes', result); }); var caAttrs = [{ name: 'commonName', value: caCert.subject.getField('CN').value }, { name: 'countryName', value: caCert.subject.getField('C').value shortName: 'ST', value: caCert.subject.getField('ST').value name: 'localityName', value: caCert.subject.getField('L').value name: 'organizationName', value: caCert.subject.getField('O').value shortName: 'OU', value: caCert.subject.getField('OU').value }]; cert.setIssuer(caAttrs); 사용자인증서와 Ca인증서를 리턴
12
인증서 발급 응답 Forgecert.js – Client JS // 인증서 발급 응답
socket.on('certRes', function(data){ userCert.value = data.cert; caCert.value = data.caCert; userCertPem = data.cert; caCertPem = data.caCert; var uCert = pki.certificateFromPem(data.cert); var cCert = pki.certificateFromPem(data.caCert); var verified = cCert.verify(uCert); verify.value = verified; });
13
발급 결과 표시 Forgecert.html - UI 화면에 표시 파일로 저장하기 로컬스토리지에 저장하기 <hr>
<h1>인증서 발급 결과</h1> RSA public key: <textarea class="form-control" rows="5" id="userPub" readonly></textarea> RSA private key: <textarea class="form-control" rows="5" id="userPriv" readonly></textarea> Certificate: <textarea class="form-control" rows="5" id="userCert" readonly></textarea> CA Certificate: <textarea class="form-control" rows="5" id="caCert" readonly></textarea> 인증서 검증 결과: <input type="text" id="verify" class="form-control" readonly> <button id="fileSaveButton" class="btn btn-primary">개인키, 인증서를 파일로 저장하기</button> <button id="lsSaveButton" class="btn btn-primary">개인키, 인증서를 로컬스토리지에 저장하기</button> <p id="filestatus"></p> 화면에 표시 파일로 저장하기 로컬스토리지에 저장하기
14
저장하기 Forgecert.js – Client JS function infolabel(str, append) {
if (append) $('#filestatus')[0].innerHTML += str; else $('#filestatus')[0].innerHTML = str; } fileSaveButton.addEventListener('click', function(){ var uripridata = 'data:application/text;charset=utf-8,' + encodeURIComponent(privateKeyPem); // 개인키(PEM) var uricerdata = 'data:application/text;charset=utf-8,' + encodeURIComponent(userCertPem); // 인증서(CER) var uricacerdata = 'data:application/text;charset=utf-8,' + encodeURIComponent(caCertPem); // 인증서(CER) infolabel('앞으로 인증서를 활용하려면 다음의 인증서 파일과 개인키 파일을 다운로드 받아 저장하세요.<br />', 1); infolabel('<a href=' + uripridata + ' download=\"userPrivateKey.pem\">개인키 파일 저장 - userPrivateKey.pem </a> <br>', 1); infolabel('<a href=' + uricerdata + ' download=\"userCert.pem\">인증서 파일 저장 - userCert.pem </a> <br>', 1); infolabel('<a href=' + uricacerdata + ' download=\"caCert.pem\">CA 인증서 파일 저장 - caCert.pem </a> <br>', 1); }); lsSaveButton.addEventListener('click', function(){ localStorage.setItem('priv', privateKeyPem); localStorage.setItem('cert', userCertPem); localStorage.setItem('cacert', caCertPem);
15
파일에서 읽어오기 Forgecert.html <hr>
<h1>개인키, 인증서를 파일에서 읽어오기</h1> 개인키 읽어오기: userPrivateKey.pem <input type="file" id="readPrivateKey" /> <br> 인증서 읽어오기: userCert.pem <input type="file" id="readCert" /> <br> CA인증서 읽어오기: caCert.pem <input type="file" id="readCaCert" /> <br> User private key: <textarea class="form-control" rows="5" id="userPriv1" readonly></textarea> User Certificate: <textarea class="form-control" rows="5" id="userCert1" readonly></textarea> CA Certificate: <textarea class="form-control" rows="5" id="caCert1" readonly></textarea>
16
파일에서 읽어오기 readPrivateKey.addEventListener('change', readPrivFile); readCert.addEventListener('change', readCertFile); readCaCert.addEventListener('change', readCaCertFile); function readPrivFile(e) { var file = e.target.files[0]; if (!file) return; var reader = new FileReader(); reader.onload = function(e) { var contents = e.target.result; userPriv1.value = contents; }; reader.readAsText(file); } function readCertFile(e) { userCert1.value = contents; function readCaCertFile(e) { caCert1.value = contents; Forgecert.js
17
로컬스토리지에서 읽어오기 Forgecert.html <hr>
<h1>개인키, 인증서를 로컬스토리지에서 읽어오기</h1> <button id="lsReadButton" class="btn btn-primary">개인키, 인증서를 로컬스토리지에서 읽어오기</button> <button id="lsClearButton" class="btn btn-primary">로컬스토리지 지우기</button> <br> User private key: <textarea class="form-control" rows="5" id="userPriv2" readonly></textarea> User Certificate: <textarea class="form-control" rows="5" id="userCert2" readonly></textarea> CA Certificate: <textarea class="form-control" rows="5" id="caCert2" readonly></textarea> 인증서 검증 결과: <input type="text" id="verify2" class="form-control" readonly>
18
로컬스토리지에서 읽어오기 Forgecert.js
lsReadButton.addEventListener('click', function(){ userPriv2.value = localStorage.getItem('priv'); userCert2.value = localStorage.getItem('cert'); caCert2.value = localStorage.getItem('cacert'); var uCert = pki.certificateFromPem(localStorage.getItem('cert')); var cCert = pki.certificateFromPem(localStorage.getItem('cacert')); var verified = cCert.verify(uCert); verify2.value = verified; }); lsClearButton.addEventListener('click', function(){ userPriv2.value=''; userCert2.value=''; caCert2.value=''; localStorage.clear();
19
공용서버에서 운영하기 클라이언트 자바스크립트 파일의 소켓접속주소 확인 Forgecert.js – 로컬 운영시
// Connect to socket.io var socket = io.connect(' //var socket = io.connect(' Forgecert.js – 공용서버 운영시 // Connect to socket.io //var socket = io.connect(' var socket = io.connect('
Similar presentations