@ -9,7 +9,7 @@ var keymgr;
var keyring = new kbpgp . keyring . KeyRing ( ) ;
/ * *
* Load and unlock the private key in localstorage , prompting user as needed . If there is no key , generates , saves , and loads a new one .
* Load and unlock the private key in localstorage , prompting user as needed .
* @ param { function } callback Passed two arguments : message for user , and boolean true if OK false if error .
* @ returns { undefined }
* /
@ -20,30 +20,39 @@ function loadKeyFromLocalStorage(callback) {
}
$ ( "#lockstatus" ) . css ( "display" , "none" ) ;
if ( ! inStorage ( "signingkey" ) || getStorage ( "signingkey" ) == "undefined" ) {
showPasswordPrompt ( "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." , function ( pass ) {
generatePrivateKey ( getStorage ( "notary_name" ) + " <" + ( inStorage ( "notary_email" ) ? getStorage ( "notary_email" ) : "null@null.com" ) + ">" , pass , function ( key ) {
callback ( "You do not have a private key. Click Settings to create one." , false ) ;
return ;
} else {
showPasswordPrompt ( "Enter password to unlock signing key:" , function ( pass ) {
loadPrivateKey ( getStorage ( "signingkey" ) , pass , function ( key ) {
if ( typeof key == "undefined" ) {
callback ( "Could not generate key." , false ) ;
callback ( "Could not unlock key. Password is probably incorrect .", false ) ;
return ;
}
keymgr = key ;
keyring . add _key _manager ( keymgr ) ;
setStorage ( "signingkey" , keymgr . armored _pgp _private ) ;
callback ( "Signing key generated." , true ) ;
callback ( "Private key unlocked." , true ) ;
} ) ;
} ) ;
} else {
showPasswordPrompt ( "Enter password to unlock signing key:" , function ( pass ) {
loadPrivateKey ( getStorage ( "signingkey" ) , pass , function ( key ) {
}
}
function createKey ( callback ) {
if ( ! inStorage ( "signingkey" ) || getStorage ( "signingkey" ) == "undefined" ) {
showPasswordPrompt ( "Generating a new private key (might take a while, be patient). Enter a password to protect it. You'll need to memorize or write down this password; it cannot be recovered." , function ( pass ) {
generatePrivateKey ( getStorage ( "notary_name" ) + " <" + ( inStorage ( "notary_email" ) ? getStorage ( "notary_email" ) : "noemailaddressprovided@example.com" ) + ">" , pass , function ( key ) {
if ( typeof key == "undefined" ) {
callback ( "Could not unlock key. Password is probably incorrect." , false ) ;
callback ( "Could not generate key .", false ) ;
return ;
}
keymgr = key ;
keyring . add _key _manager ( keymgr ) ;
callback ( "Signing key unlocked." , true ) ;
setStorage ( "signingkey" , keymgr . armored _pgp _private ) ;
callback ( "Private key generated." , true ) ;
} ) ;
} ) ;
} else {
callback ( "You already have a private key. You must erase it before generating a new one." , false ) ;
}
}
@ -63,6 +72,16 @@ function loadKeyFromLocalStorageWithUserFeedback() {
} ) ;
}
function createKeyWithUserFeedback ( ) {
createKey ( function ( msg , ok ) {
if ( ok ) {
showToast ( "<i class='fas fa-check'></i> " + msg ) ;
} else {
showAlert ( "Error: " + msg ) ;
}
} ) ;
}
/ * *
* Load a private key .
* @ param { string } armoredkey PGP private key
@ -184,18 +203,68 @@ function generatePrivateKey(userid, passphrase, callback) {
} , 100 ) ;
}
function exportPublicKey ( ) {
loadKeyFromLocalStorage ( function ( message , ok ) {
if ( ok ) {
function exportPublicKeyToFile ( ) {
getOwnPublicKey ( function ( pgp _public ) {
if ( pgp _public == false ) {
showAlert ( "Something went wrong." ) ;
} else {
openSaveFileDialog ( function ( path ) {
keymgr . export _pgp _public ( { } , function ( err , pgp _public ) {
if ( err ) {
showAlert ( "Something went wrong." ) ;
} else {
writeToFile ( path , pgp _public ) ;
}
} ) ;
writeToFile ( path , pgp _public ) ;
showAlert ( "Public key saved." ) ;
} , "public-key.asc" , ".asc" ) ;
}
} ) ;
}
function exportPublicKeyToRegistry ( ) {
if ( ! inStorage ( "signingkey" ) || getStorage ( "signingkey" ) == "undefined" ) {
showAlert ( "You must create and back up your private key first." ) ;
return ;
}
showOkCancelPrompt ( "Double-check that your notary profile is complete and that you pressed the Save button after making any changes before continuing." , function ( ok ) {
if ( ! ok ) {
return ;
}
getOwnPublicKey ( function ( pgp _public ) {
if ( pgp _public == false ) {
showAlert ( "Something went wrong." ) ;
} else {
submitPublicKeyToRegistry (
pgp _public ,
getStorage ( "notary_name" ) ,
getStorage ( "notary_email" ) ,
getStorage ( "notary_location" ) ,
getStorage ( "notary_expires" ) ,
getStorage ( "notary_idnumber" ) ,
getStorage ( "notary_state" ) ,
function ( msg , ok ) {
if ( ! ok ) {
showAlert ( "Error: " + msg ) ;
} else {
showAlert ( msg ) ;
}
}
) ;
}
} ) ;
} ) ;
}
/ * *
* Get user ' s own public key , prompting for key password if needed .
* @ param { function } callback cb ( result ) : public key string or false on error
* @ returns { undefined }
* /
function getOwnPublicKey ( callback ) {
loadKeyFromLocalStorage ( function ( message , ok ) {
if ( ok ) {
keymgr . export _pgp _public ( { } , function ( err , pgp _public ) {
if ( err ) {
callback ( false ) ;
} else {
callback ( pgp _public ) ;
}
} ) ;
} else {
showAlert ( "Error: " + message ) ;
}
@ -324,14 +393,11 @@ function calculateSHA256HashOfString(str) {
function openPublicKeyFile ( ) {
openFileDialog ( function ( path , html5file ) {
var importpk = function ( keyfile ) {
kbpgp . KeyManager . import _from _armored _pgp ( {
armored : keyfile
} , function ( err , pubkeymgr ) {
if ( ! err ) {
keyring . add _key _manager ( pubkeymgr ) ;
addPublicKeyToKeyring ( keyfile , function ( res ) {
if ( res === true ) {
showAlert ( "Public key file loaded. You can now analyze PDFs signed by the key's owner." ) ;
} else {
showAlert ( "Error loading public key: " + er r) ;
showAlert ( "Error loading public key: " + res ) ;
}
} ) ;
} ;
@ -349,6 +415,150 @@ function openPublicKeyFile() {
} , ".asc" ) ;
}
/ * *
*
* @ param { type } keyfile
* @ param { type } callback cb ( result ) : result is true if successful , an error string if failed .
* @ returns { undefined }
* /
function addPublicKeyToKeyring ( keyfile , callback ) {
kbpgp . KeyManager . import _from _armored _pgp ( {
armored : keyfile
} , function ( err , pubkeymgr ) {
if ( ! err ) {
keyring . add _key _manager ( pubkeymgr ) ;
callback ( true ) ;
} else {
callback ( err ) ;
}
} ) ;
}
/ * *
* Look up a full or partial public key fingerprint with the Netsyms notary registry .
* @ param { string } fingerprint
* @ param { function } callback cb ( result ) : ` result ` is an array of notary info and keys ( see below ) , or ` false ` if there was an error or no results .
* @ returns { undefined }
*
* result = [ {
* fingerprint ,
* name ,
* email ,
* location ,
* commissionexpires ,
* idnumber ,
* state ,
* publickey
* } ]
*
* All but fingerprint and publickey could be null .
*
* /
function lookupPublicKey ( fingerprint , callback ) {
$ . ajax ( {
url : "https://data.netsyms.net/v1/notary/fetchkey/" ,
dataType : "json" ,
data : {
fingerprint : fingerprint
} ,
success : function ( resp ) {
if ( resp . count == 0 ) {
callback ( false ) ;
return ;
}
callback ( resp . results ) ;
} ,
error : function ( ) {
callback ( false ) ;
}
} ) ;
}
/ * *
* Import multiple public keys and only callback when all are done .
* @ param { type } keys see lookupPublicKey ( )
* @ param { function } callback
* @ returns { undefined }
* /
function importPublicKeysFromRegistry ( keys , callback ) {
var i = 0 ;
var loop = function ( keys ) {
addPublicKeyToKeyring ( keys [ i ] . publickey , function ( ) {
i ++ ;
if ( i < keys . length ) {
loop ( keys ) ;
} else {
callback ( ) ;
}
} ) ;
} ;
loop ( keys ) ;
}
/ * *
* Upload a public key to the Netsyms notary registry server .
* @ param { string } pubkey PGP public key file contents , armored
* @ param { string } name Notary name
* @ param { string } email Notary email
* @ param { string } location Notary location
* @ param { string } expires Commission expiration date ; server will parse .
* @ param { string } idnumber Commission ID number
* @ param { string } state Two - char state
* @ param { function } callback ( ( string ) message , ( bool ) okaytrue _errorfalse )
* @ returns { undefined }
* /
function submitPublicKeyToRegistry ( pubkey , name , email , location , expires , idnumber , state , callback ) {
$ . ajax ( {
url : "https://data.netsyms.net/v1/notary/publishkey/" ,
method : "POST" ,
dataType : "json" ,
data : {
publickey : pubkey ,
name : name ,
email : email ,
location : location ,
commissionexpires : expires ,
idnumber : idnumber ,
state : state
} ,
success : function ( resp ) {
if ( resp . status == "OK" ) {
callback ( resp . msg , true ) ;
} else if ( resp . status == "ERROR" ) {
callback ( resp . msg , false ) ;
} else {
callback ( "The registry server didn't send a valid response." , false ) ;
}
} ,
error : function ( ) {
callback ( "There was a problem communicating with the registry server. Try again later." , false ) ;
}
} ) ;
}
/ * *
* Erase the local private key data with lots of prompting and dire warnings .
* @ returns { undefined }
* /
function erasePrivateKey ( ) {
showOkCancelPrompt ( "<div style=\"background: black; padding: 1rem;\" > < b > < i class = 'fas fa-skull-crossbones' > < / i > D A N G E R : T H I S W I L L R E S U L T I N D A T A L O S S - - R E A D C A R E F U L L Y < / b > < b r > < b r > \ n \
Erasing your private key means you won ' t be able to notarize or sign electronic documents without generating a new key . \ n \
If you have not exported your public key , electronically verifying documents you have signed will be impossible . \ n \
If you plan on using your private key in the future , press cancel and back up your private key to a file . \ n \
Some states require you use the same key for the entire length of your commission . \ n \
< br > < br > < b > IF YOU CONTINUE , YOUR PRIVATE KEY WILL NOT BE RECOVERABLE WITHOUT A BACKUP . < / b > < / d i v > " , f u n c t i o n ( o k ) {
if ( ! ok ) {
return ;
}
var txt = prompt ( "To erase your private key, type \"ERASE MY SIGNING KEY\"" ) ;
if ( txt . toUpperCase ( ) != "ERASE MY SIGNING KEY" ) {
return ;
}
unloadKey ( ) ;
localStorage . removeItem ( "signingkey" ) ;
alert ( "Signing key erased." ) ;
} ) ;
}
/ * *
* Show visual indicator when private key is not loaded / unlocked .
* @ returns { undefined }
@ -359,4 +569,5 @@ setInterval(function () {
} else {
$ ( "#lockstatus" ) . css ( "display" , "none" ) ;
}
} , 1000 ) ;
}
, 1000 ) ;