Skip to content

Instantly share code, notes, and snippets.

@tpolecat
Created July 22, 2020 18:35
Show Gist options
  • Save tpolecat/ab9c18be00cbd32630d6ae5f0300da98 to your computer and use it in GitHub Desktop.
Save tpolecat/ab9c18be00cbd32630d6ae5f0300da98 to your computer and use it in GitHub Desktop.
GPG ASCII-amored exported text to JCA keys
import java.io.ByteArrayInputStream
import java.security.PrivateKey
import java.security.PublicKey
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.bouncycastle.openpgp.operator.jcajce._
import org.bouncycastle.openpgp._
import scala.util.control.NonFatal
/**
* Methods to turn GPG ASCII-amored exported text into JCA keys. Many thanks to Twitter friends,
* whose help deferred my burning the earth to a cinder for a few days longer. I have no idea what
* kind of exceptions this stuff throws so Throwable is what you get if it fails, sorry. This works
* with "org.bouncycastle" % "bcpg-jdk15on" % "1.66"
*/
object JcaKeyBullshit {
// The demo code hints that this is threadsafe and can be shared.
private val provider = new BouncyCastleProvider
/** Turn the output from `gpg --armor --export <key>` into a JCA PublicKey. */
def publicKey(pgpArmorText: String): Either[Throwable, PublicKey] =
try {
val is = PGPUtil.getDecoderStream(new ByteArrayInputStream(pgpArmorText.getBytes("US-ASCII")))
val kr = new PGPPublicKeyRingCollection(is, new JcaKeyFingerprintCalculator)
val pk = kr.iterator.next.getPublicKey
val kc = new JcaPGPKeyConverter
Right(kc.getPublicKey(pk))
} catch {
case NonFatal(e) => Left(e)
}
/** Turn the output from `gpg --armor --export-secret-keys <key>` into a JCA PrivateKey. */
def privateKey(pgpArmorText: String, passphrase: String): Either[Throwable, PrivateKey] =
try {
val is = PGPUtil.getDecoderStream(new ByteArrayInputStream(pgpArmorText.getBytes("US-ASCII")))
val kr = new PGPSecretKeyRingCollection(is, new JcaKeyFingerprintCalculator)
val sk = kr.iterator.next.getSecretKey
val kd = new JcePBESecretKeyDecryptorBuilder().setProvider(provider).build(passphrase.toCharArray)
val pk = sk.extractPrivateKey(kd)
val kc = new JcaPGPKeyConverter
Right(kc.getPrivateKey(pk))
} catch {
case NonFatal(e) => Left(e)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment