Skip to content
Browse files

if passphrase is incorrect ask 3 times or giveup immediately

  • Loading branch information...
1 parent 4a197b2 commit 0f624a9f1f5026ac3bf32b90f1ff2926a109e07b @jozic jozic committed
View
17 gpg-library/src/main/scala/com/jsuereth/pgp/PrivateKey.scala
@@ -7,6 +7,9 @@ import java.util.Date
import org.bouncycastle.bcpg._
import org.bouncycastle.openpgp._
+class IncorrectPassphraseException(msg: String) extends RuntimeException(msg)
+
+
/** A SecretKey that can be used to sign things and decrypt messages. */
class SecretKey(val nested: PGPSecretKey) {
def keyID = nested.getKeyID
@@ -21,7 +24,7 @@ class SecretKey(val nested: PGPSecretKey) {
* Note: This will close all streams.
*/
def signStream(in: InputStream, signature: OutputStream, pass: Array[Char]): Unit = {
- val privateKey = nested.extractPrivateKey(pass, "BC")
+ val privateKey = extractPrivateKey(pass)
val sGen = new PGPSignatureGenerator(nested.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1, "BC")
sGen.initSign(PGPSignature.BINARY_DOCUMENT, privateKey)
val out = new BCPGOutputStream(new ArmoredOutputStream(signature))
@@ -53,7 +56,7 @@ class SecretKey(val nested: PGPSecretKey) {
/** Encodes and signs a message into a PGP message. */
def signMessageStream(input: InputStream, name: String, length: Long, output: OutputStream, pass: Array[Char], lastMod: Date = new Date): Unit = {
val armoredOut = new ArmoredOutputStream(output)
- val pgpPrivKey = nested.extractPrivateKey(pass, "BC")
+ val pgpPrivKey = extractPrivateKey(pass)
val sGen = new PGPSignatureGenerator(nested.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1, "BC")
sGen.initSign(PGPSignature.BINARY_DOCUMENT, pgpPrivKey)
for(name <- this.publicKey.userIDs) {
@@ -97,7 +100,7 @@ class SecretKey(val nested: PGPSecretKey) {
// TODO - notation optional?
def signPublicKey(key: PublicKey, notation: (String,String), pass: Array[Char]): PublicKey = {
val out = new ArmoredOutputStream(new ByteArrayOutputStream())
- val pgpPrivKey = nested.extractPrivateKey(pass, "BC")
+ val pgpPrivKey = extractPrivateKey(pass)
val sGen = new PGPSignatureGenerator(
nested.getPublicKey().getAlgorithm(),
HashAlgorithmTags.SHA1,
@@ -184,7 +187,7 @@ class SecretKey(val nested: PGPSecretKey) {
}
// TODO - Better exception?
if(pbe.getKeyID != this.keyID) throw new KeyNotFoundException(pbe.getKeyID)
- val privKey = nested.extractPrivateKey(passPhrase, "BC")
+ val privKey = extractPrivateKey(passPhrase)
val clear = pbe.getDataStream(privKey, "BC")
val plainFact = new PGPObjectFactory(clear)
// Handle compressed + uncompressed data here.
@@ -205,6 +208,12 @@ class SecretKey(val nested: PGPSecretKey) {
}
}
+ private[this] def extractPrivateKey(passPhrase: Array[Char]) =
+ try nested.extractPrivateKey(passPhrase, "BC")
+ catch {
+ case e: PGPException if e.getMessage.contains("checksum mismatch") => throw new IncorrectPassphraseException("Incorrect passhprase")
+ }
+
def userIDs = new Traversable[String] {
def foreach[U](f: String => U) = {
val i = nested.getUserIDs
View
33 src/main/scala/SbtPgpCommandContext.scala
@@ -6,9 +6,7 @@ import sbt.Keys.TaskStreams
case class SbtPgpStaticContext(
publicKeyRingFile: File,
- secretKeyRingFile: File) extends cli.PgpStaticContext {
-
-}
+ secretKeyRingFile: File) extends cli.PgpStaticContext
/** Context used by PGP commands as they execute. */
case class SbtPgpCommandContext(
@@ -23,12 +21,33 @@ case class SbtPgpCommandContext(
def readHidden(msg: String): String = System.out.synchronized {
SimpleReader.readLine(msg, Some('*')) getOrElse sys.error("Failed to grab input")
}
- def inputPassphrase = readHidden("Please enter PGP passphrase: ").toCharArray
- def withPassphrase[U](f: Array[Char] => U): U =
- PasswordCache.withValue(
+ def inputPassphrase = readHidden("Please enter PGP passphrase (or ENTER to abort): ") match {
+ case s: String if (!s.isEmpty) => s.toCharArray
+ case _ => sys.error("Empty passphrase. aborting...")
+ }
+
+ def withPassphrase[U](f: Array[Char] => U): U = {
+ retry[U, IncorrectPassphraseException](3){
+ PasswordCache.withValue(
key = ctx.secretKeyRingFile.getAbsolutePath,
default = optPassphrase getOrElse inputPassphrase)(f)
-
+ } match {
+ case Right(u) => u
+ case Left(e) => sys.error("Wrong passphrase. aborting...")
+ }
+ }
+
+ @annotation.tailrec
+ private def retry[A, E <: Exception](n: Int)(body: => A)(implicit desired: Manifest[E]): Either[E, A] = {
+ try
+ return Right(body)
+ catch {
+ case e: Exception if desired.erasure.isAssignableFrom(e.getClass) => if (n <= 1) return Left(e.asInstanceOf[E])
+ }
+ retry[A, E](n - 1)(body)
+ }
+
+
def log = s.log
// TODO - Is this the right thing to do?
def output[A](msg: => A): Unit = println(msg)
View
2 src/main/scala/com/jsuereth/pgp/cli/SignKey.scala
@@ -30,7 +30,7 @@ case class SignKey(pubKey: String, notation: (String,String)) extends PgpCommand
val newpubring = ring :+ newkey
(ctx.publicKeyRing removeRing ring) :+ newpubring
case Seq() => sys.error("Could not find key: " + pubKey)
- case matches => sys.error("Found more than on pulic key: " + matches.map(_._2).mkString(","))
+ case matches => sys.error("Found more than on public key: " + matches.map(_._2).mkString(","))
}
newpubringcol saveToFile ctx.publicKeyRingFile
}

0 comments on commit 0f624a9

Please sign in to comment.
Something went wrong with that request. Please try again.