Add key import/export (close #6)
This commit is contained in:
parent
d892fe81ed
commit
553af5e84e
63
index.html
63
index.html
@ -13,28 +13,57 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||||||
<link rel="stylesheet" href="css/main.css" />
|
<link rel="stylesheet" href="css/main.css" />
|
||||||
|
|
||||||
<div class="modal fade" id="settingsModal" tabindex="-1" aria-labelledby="settingsModalLabel" aria-hidden="true">
|
<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-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title" id="settingsModalLabel">Settings</h5>
|
<h5 class="modal-title" id="settingsModalLabel">Settings</h5>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
Name: <input class="form-control" type="text" id="notary_name" />
|
<div class="row">
|
||||||
Location (county/residing at): <input class="form-control" type="text" id="notary_location" />
|
<div class="col-12 col-lg-6">
|
||||||
Commission expiration: <input class="form-control" type="text" id="notary_expires" />
|
<h4>Notary Profile</h4>
|
||||||
Commission number: <input class="form-control" type="text" id="notary_idnumber" />
|
Name: <input class="form-control" type="text" id="notary_name" />
|
||||||
State: <select class="form-control" id="notary_state">
|
Location (county/residing at): <input class="form-control" type="text" id="notary_location" />
|
||||||
<option selected></option>
|
Commission expiration: <input class="form-control" type="text" id="notary_expires" />
|
||||||
<option value="mt">Montana</option>
|
Commission number: <input class="form-control" type="text" id="notary_idnumber" />
|
||||||
</select>
|
State: <select class="form-control" id="notary_state">
|
||||||
<br>
|
<option selected></option>
|
||||||
Stamp Preview:<br>
|
<option value="mt">Montana</option>
|
||||||
<img src="" id="stamp-preview" />
|
</select>
|
||||||
<br>
|
<br>
|
||||||
Notary Signature:<br>
|
Stamp Preview:<br>
|
||||||
<img src="" id="signature-preview" /><br>
|
<img src="" id="stamp-preview" />
|
||||||
<div class="btn btn-primary" onclick="activateNotarySignaturePad()"><i class="fas fa-signature"></i> Draw Signature</div>
|
<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>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
<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>
|
<a class="nav-link" href="#" onclick="addPDF()"><i class="fas fa-file-pdf"></i> Add PDF</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<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>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="#" onclick="openSettingsModal()"><i class="fas fa-cog"></i> Settings</a>
|
<a class="nav-link" href="#" onclick="openSettingsModal()"><i class="fas fa-cog"></i> Settings</a>
|
||||||
|
78
js/crypto.js
78
js/crypto.js
@ -13,8 +13,12 @@ var keymgr;
|
|||||||
* @returns {undefined}
|
* @returns {undefined}
|
||||||
*/
|
*/
|
||||||
function loadKeyFromLocalStorage(callback) {
|
function loadKeyFromLocalStorage(callback) {
|
||||||
|
if (typeof keymgr != "undefined") {
|
||||||
|
callback("Key already loaded.", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!inStorage("signingkey") || getStorage("signingkey") == "undefined") {
|
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) {
|
generatePrivateKey(getStorage("notary_name") + " <null@null.com>", pass, function (key) {
|
||||||
if (typeof key == "undefined") {
|
if (typeof key == "undefined") {
|
||||||
callback("Could not generate key.", false);
|
callback("Could not generate key.", false);
|
||||||
@ -25,7 +29,7 @@ function loadKeyFromLocalStorage(callback) {
|
|||||||
callback("Signing key generated.", true);
|
callback("Signing key generated.", true);
|
||||||
});
|
});
|
||||||
} else {
|
} 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) {
|
loadPrivateKey(getStorage("signingkey"), pass, function (key) {
|
||||||
if (typeof key == "undefined") {
|
if (typeof key == "undefined") {
|
||||||
callback("Could not unlock key. Password is probably incorrect.", false);
|
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.
|
* Load a private key.
|
||||||
* @param {string} armoredkey PGP private key
|
* @param {string} armoredkey PGP private key
|
||||||
@ -122,3 +136,63 @@ 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…
x
Reference in New Issue
Block a user