Before we get to the Scala code, we must first use Java's keytool to create a self-signed certificate.
In real-life, you'd probably buy one from Verisign for example. The archive file format chosen is PKCS12.
keytool -genkey -alias tj -keystore mykeystore -storepass storepass -validity 365 -keyalg RSA -keysize 2048 -storetype pkcs12Once you have answered the questions, you can list the aliases using the following command:
keytool -keystore mykeystore -storepass storepass -list -storetype pkcs12Should output:
Keystore type: PKCS12 Keystore provider: SunJSSE Your keystore contains 1 entry tj, Oct 12, 2014, PrivateKeyEntry, Certificate fingerprint (SHA1): 52:6B:0D:05:9E:CE:5A:CA:5E:EF:74:C9:51:FE:46:8D:E6:CE:4F:11Let's get to the coding part. We will extract the private key from the store to digitally sign a document. I usually first create a digest from the initial document and store this digest as base 64. But there is no need for this step.
def createDigest(legalDocument: String): Array[Byte] = { val md = MessageDigest.getInstance("SHA-256") md.update(legalDocument.getBytes) md.digest() }to be called like this:
val alias = "tj" val password = "storepass".toCharArray val legalDoc = createDigest("This is a legal document I must digitally sign")legalDoc is an array of bytes - it contains a SHA-256 digest from the initial document.
The code to list the keystore entries, just to make sure we are on the right path:
def listStoreEntries(password: Array[Char]): KeyStore = { val keyStoreDefaultType = KeyStore.getDefaultType val keyStore = KeyStore.getInstance("pkcs12") keyStore.load(new FileInputStream("mykeystore"), password) val aliases = keyStore.aliases() while(aliases.hasMoreElements) { val alias = aliases.nextElement() log(s" Alias: $alias") } keyStore }listStoreEntries returns the initialized keystore. Let's now sign the legal document and return a base 64 encoded digital signature:
def signLegalDocument(keystore: KeyStore, alias: String, password: Array[Char], legalDoc: Array[Byte]): String = { val privateKey = keystore.getKey(alias, password) val dsig = Signature.getInstance("MD5withRSA") dsig.initSign(privateKey.asInstanceOf[PrivateKey]) dsig.update(legalDoc) val signature = dsig.sign() Base64.getEncoder.encodeToString(signature) }And the code to verify the signature:
def verifyDigitalSignature(keystore: KeyStore, alias: String, legalDoc: Array[Byte], signature: String): Unit = { val certificate = keystore.getCertificate(alias) val x509Certificate = certificate.asInstanceOf[X509Certificate] val publicKey = x509Certificate.getPublicKey val dsig = Signature.getInstance("MD5withRSA") dsig.initVerify(publicKey) val sig = Base64.getDecoder.decode(signature) dsig.update(legalDoc) val verifiedSig = dsig.verify(sig) log(s"Has the legal document signature successfully been verified? $verifiedSig") require(verifiedSig == true) }The whole main method:
def main(args: Array[String]) { val alias = "tj" val password = "storepass".toCharArray val legalDoc = createDigest("This is a legal document I must digitally sign") val keyStore = listStoreEntries(password) val signature = signLegalDocument(keyStore, alias, password, legalDoc) verifyDigitalSignature(keyStore, alias, legalDoc, signature) } def log(ref: Any) = println(ref)How do I import my self-signed certificate into Windows cert manager?
Just rename the keystore from mykeystore to mykeystore.pfx On Windows, simple double-click on it and follow the instructions.
Open certmgr.msc via the run command or from a DOS console - under Certificates - Currrent User, Personal, Certificates you should see your previously create certificate using Java's keytool.
No comments:
Post a Comment