Add initial implementation

This commit implements a basic static HTML page that uses Bootstrap 4
for layout and node-forge to generate a RSA key pair and a certificate
signing request. The subject of the CSR and the key size can be chosen
by the user.

The implementation uses gulp to collect static assets and to allow
bootstrap customization.
This commit is contained in:
Jan Dittberner 2020-11-22 11:28:28 +01:00
commit 564c1bd76b
7 changed files with 5121 additions and 0 deletions

111
src/index.html Normal file
View file

@ -0,0 +1,111 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="../public/css/styles.min.css">
<meta name="theme-color" content="#ffffff">
<title>CSR generation in browser</title>
</head>
<body>
<div class="container">
<h1>CSR generation in browser</h1>
<div class="row">
<div class="col-12">
<form id="csr-form">
<div class="form-group">
<label for="nameInput">Your name</label>
<input type="text" class="form-control" id="nameInput" aria-describedby="nameHelp" required
minlength="3">
<small id="nameHelp" class="form-text text-muted">Please input your name as it should be added to
your certificate</small>
</div>
<fieldset class="form-group">
<legend>RSA Key Size</legend>
<div class="form-check">
<input class="form-check-input" type="radio" name="keySize" id="size3072" value="3072"
checked>
<label class="form-check-label" for="size3072">3072 Bit</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="keySize" id="size2048" value="2048">
<label class="form-check-label" for="size2048">2048 Bit (not recommended</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="keySize" id="size4096" value="4096">
<label class="form-check-label" for="size4096">4096 Bit</label>
</div>
<small id="keySizeHelp" class="form-text text-muted">An RSA key pair will be generated in your
browser. Longer key sizes provide better security but take longer to generate.</small>
</fieldset>
<button type="submit" id="gen-csr-button" class="btn btn-primary">Generate Signing Request</button>
</form>
</div>
</div>
<div id="status-block" class="d-none row">
<div class="col-12">
<div class="d-flex align-items-center">
<strong id="status-text">Loading ...</strong>
<div class="spinner-border ml-auto" id="status-spinner" role="status" aria-hidden="true"></div>
</div>
</div>
</div>
<pre id="key"></pre>
<pre id="csr"></pre>
</div>
<script src="../public/js/jquery.slim.min.js"></script>
<script src="../public/js/forge.all.min.js"></script>
<script src="../public/js/bootstrap.bundle.min.js"></script>
<script>
const keyElement = document.getElementById('key');
document.getElementById('csr-form').onsubmit = function (event) {
const subject = event.target["nameInput"].value;
const keySize = parseInt(event.target["keySize"].value);
if (isNaN(keySize)) {
return false;
}
const spinner = document.getElementById('status-spinner');
const statusText = document.getElementById('status-text');
const statusBlock = document.getElementById('status-block');
statusBlock.classList.remove('d-none');
spinner.classList.remove('d-none');
const state = forge.pki.rsa.createKeyPairGenerationState(keySize, 0x10001);
statusText.innerHTML = 'started key generation';
const startDate = new Date();
const step = function () {
let duration = (new Date()).getTime() - startDate.getTime();
let seconds = Math.floor(duration / 100) / 10;
if (!forge.pki.rsa.stepKeyPairGenerationState(state, 100)) {
setTimeout(step, 1);
statusText.innerHTML = `key generation running for ${seconds} seconds`;
} else {
statusText.innerHTML = `key generated in ${seconds} seconds`
spinner.classList.add('d-none');
const keys = state.keys;
keyElement.innerHTML = forge.pki.privateKeyToPem(keys.privateKey);
const csr = forge.pki.createCertificationRequest();
csr.publicKey = keys.publicKey;
csr.setSubject([{
name: 'commonName',
value: subject,
}]);
csr.sign(keys.privateKey, forge.md.sha256.create());
const verified = csr.verify();
if (verified) {
document.getElementById("csr").innerHTML = forge.pki.certificationRequestToPem(csr);
}
}
};
setTimeout(step);
return false;
};
</script>
</body>
</html>