Add key import/export (close #6)

master
Skylar Ittner 3 years ago
parent d892fe81ed
commit 553af5e84e

@ -13,28 +13,57 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
<link rel="stylesheet" href="css/main.css" />
<div class="modal fade" id="settingsModal" tabindex="-1" aria-labelledby="settingsModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="settingsModalLabel">Settings</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Name: <input class="form-control" type="text" id="notary_name" />
Location (county/residing at): <input class="form-control" type="text" id="notary_location" />
Commission expiration: <input class="form-control" type="text" id="notary_expires" />
Commission number: <input class="form-control" type="text" id="notary_idnumber" />
State: <select class="form-control" id="notary_state">
<option selected></option>
<option value="mt">Montana</option>
</select>
<br>
Stamp Preview:<br>
<img src="" id="stamp-preview" />
<br>
Notary Signature:<br>
<img src="" id="signature-preview" /><br>
<div class="btn btn-primary" onclick="activateNotarySignaturePad()"><i class="fas fa-signature"></i> Draw Signature</div>
<div class="row">
<div class="col-12 col-lg-6">
<h4>Notary Profile</h4>
Name: <input class="form-control" type="text" id="notary_name" />
Location (county/residing at): <input class="form-control" type="text" id="notary_location" />
Commission expiration: <input class="form-control" type="text" id="notary_expires" />
Commission number: <input class="form-control" type="text" id="notary_idnumber" />
State: <select class="form-control" id="notary_state">
<option selected></option>
<option value="mt">Montana</option>
</select>
<br>
Stamp Preview:<br>
<img src="" id="stamp-preview" />
<br>
Notary Signature:<br>
<img src="" id="signature-preview" /><br>
<div class="btn btn-primary m-1" onclick="activateNotarySignaturePad()"><i class="fas fa-signature"></i> Draw Signature</div>
</div>
<div class="col-12 col-lg-6">
<h4>Digital Signature</h4>
<p>
<b>MUST READ:</b> When you save a PDF with this tool, a cryptographic signature is attached.
This signature can be used to prove the PDF is unchanged since notarization,
and prove that you were the notary involved.
<br>
Signatures are generated using your private key, which you must keep secret.
Someone with the private key can modify a signed PDF without detection.
<b>Protect your private key like you protect your notary stamp/seal.</b>
<br>
A corresponding public key is also available; anyone with your public key can
verify you signed a document, but cannot do anything else.
It is recommended to post your public key somewhere public like a website.
This way, people can ensure documents are valid. It is also recommended to
<b>back up your private key</b> in case your computer malfunctions. This will ensure you don't need
to make a new one. A new key won't be able to verify older signatures or vice versa.
</p>
<div class="btn btn-primary m-1" onclick="loadKeyFromLocalStorageWithUserFeedback()"><i class="fas fa-unlock"></i> Create/unlock private key</div>
<div class="btn btn-primary m-1" onclick="exportPublicKey()"><i class="fas fa-file-export"></i> Export public key</div>
<br>
<div class="btn btn-danger m-1" onclick="exportPrivateKey()"><i class="fas fa-download"></i> Back up private key</div>
<div class="btn btn-danger m-1" onclick="importPrivateKey()"><i class="fas fa-upload"></i> Restore private key</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
@ -75,7 +104,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
<a class="nav-link" href="#" onclick="addPDF()"><i class="fas fa-file-pdf"></i> Add PDF</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="savePDF()"><i class="fas fa-save"></i> Save</a>
<a class="nav-link" href="#" onclick="savePDF()"><i class="fas fa-save"></i> Save Signed PDF</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="openSettingsModal()"><i class="fas fa-cog"></i> Settings</a>

@ -13,8 +13,12 @@ var keymgr;
* @returns {undefined}
*/
function loadKeyFromLocalStorage(callback) {
if (typeof keymgr != "undefined") {
callback("Key already loaded.", true);
return;
}
if (!inStorage("signingkey") || getStorage("signingkey") == "undefined") {
var pass = prompt("Generating a new signing key. Enter a password to protect it. You'll need to save this password somewhere safe; it cannot be recovered.");
var pass = prompt("Generating a new signing key (might take a while, be patient). Enter a password to protect it. You'll need to save this password somewhere safe; it cannot be recovered.");
generatePrivateKey(getStorage("notary_name") + " <null@null.com>", pass, function (key) {
if (typeof key == "undefined") {
callback("Could not generate key.", false);
@ -25,7 +29,7 @@ function loadKeyFromLocalStorage(callback) {
callback("Signing key generated.", true);
});
} else {
var pass = prompt("Enter password to unlock signing key.");
var pass = prompt("Enter password to unlock signing key:");
loadPrivateKey(getStorage("signingkey"), pass, function (key) {
if (typeof key == "undefined") {
callback("Could not unlock key. Password is probably incorrect.", false);
@ -37,6 +41,16 @@ function loadKeyFromLocalStorage(callback) {
}
}
function loadKeyFromLocalStorageWithUserFeedback() {
loadKeyFromLocalStorage(function (msg, ok) {
if (ok) {
alert(msg);
} else {
alert("Error: " + msg);
}
});
}
/**
* Load a private key.
* @param {string} armoredkey PGP private key
@ -121,4 +135,64 @@ function generatePrivateKey(userid, passphrase, callback) {
});
}
});
}
function exportPublicKey() {
loadKeyFromLocalStorage(function (message, ok) {
if (ok) {
openSaveFileDialog(function (path) {
keymgr.export_pgp_public({}, function (err, pgp_public) {
if (err) {
alert("Something went wrong.");
} else {
writeToFile(path, pgp_public);
}
});
}, "public-key.asc", ".asc");
} else {
alert("Error: " + message);
}
});
}
function exportPrivateKey() {
loadKeyFromLocalStorage(function (message, ok) {
if (ok) {
var pass = prompt("Enter a password to protect the backup key:");
openSaveFileDialog(function (path) {
keymgr.export_pgp_private({
passphrase: pass
}, function (err, pgp_private) {
if (err) {
alert("Something went wrong.");
} else {
writeToFile(path, pgp_private);
}
});
}, "private-key.asc", ".asc");
} else {
alert("Error: " + message);
}
});
}
function importPrivateKey() {
if (inStorage("signingkey") && getStorage("signingkey") != "undefined") {
if (!confirm("The restored key will replace the current key, which will be unrecoverable unless you made a backup. Continue?")) {
return;
}
}
openFileDialog(function (path) {
var keyfile = getFileAsString(path);
var pass = prompt("Enter password for imported key (password was set when exported):");
loadPrivateKey(keyfile, pass, function (key) {
if (typeof key == "undefined") {
alert("Could not import key. Password is probably incorrect.");
return;
}
keymgr = key;
setStorage("signingkey", keymgr.armored_pgp_private);
alert("Private key imported.");
});
}, ".asc");
}
Loading…
Cancel
Save