Skip to content

Commit

Permalink
allow use of private keys with no passphrase #12
Browse files Browse the repository at this point in the history
Add Key.NO_PASSPHRASE constant to signal that a key doesn't use a
passphrase (as well as Key/Subkey.noPassphrase property),
and add unit test to validate a passphrase-less key works
for signing and decryption.
  • Loading branch information
justinludwig committed Apr 13, 2018
1 parent 676d849 commit 6a9e298
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/main/java/org/c02e/jpgpj/Decryptor.java
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ protected PGPContentVerifierBuilderProvider getVerifierProvider() {
}

/**
* Builds a symmetric-encryption decryptor for the specified passphrase.
* Builds a symmetric-encryption decryptor for the specified subkey.
*/
protected PublicKeyDataDecryptorFactory buildPublicKeyDecryptor(
Subkey subkey) throws PGPException {
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/org/c02e/jpgpj/Key.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
* or all user IDs, as the message signer).
*/
public class Key {
/** Use this value to set the passphrase of a passphrase-less key. */
public static String NO_PASSPHRASE = "JPGPJ_NO_PASSPHRASE";

protected String signingUid;
protected List<Subkey> subkeys;

Expand Down Expand Up @@ -164,6 +167,15 @@ public void setPassphrase(String x) {
subkey.setPassphrase(x);
}

/**
* True to flag all subkeys as needing no passphrase to unlock;
* false to require a passphrase to be (re-)set on all subkeys.
*/
public void setNoPassphrase(boolean x) {
for (Subkey subkey : subkeys)
subkey.setNoPassphrase(x);
}

/**
* User ID strings for master subkey
* (ex ["My Name (comment) &lt;me@example.com&gt;"]).
Expand Down
24 changes: 23 additions & 1 deletion src/main/java/org/c02e/jpgpj/Subkey.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
* you must also set the subkey's passphrase, either via the
* {@link #setPassphrase} method on the subkey, or the
* {@link Key#setPassphrase} on its containing {@link Key}.
* If the subkey does not have a passphrase, set the passphrase to the
* {@link Key#NO_PASSPHRASE} constant.
*/
public class Subkey {
protected boolean forSigning;
Expand Down Expand Up @@ -139,6 +141,8 @@ public void setForDecryption(boolean x) {
/**
* Passphrase needed to unlock the private part
* of the subkey's public key-pair; or empty string.
* Use {@link Key#NO_PASSPHRASE} to signal the private part of the subkey
* is not protected by a passphrase.
*/
public String getPassphrase() {
return passphrase;
Expand All @@ -147,11 +151,29 @@ public String getPassphrase() {
/**
* Passphrase needed to unlock the private part
* of the subkey's public key-pair; or empty string.
* Use {@link Key#NO_PASSPHRASE} to signal the private part of the subkey
* is not protected by a passphrase.
*/
public void setPassphrase(String x) {
passphrase = x != null ? x : "";
}

/**
* True if no passphrase is needed to unlock the private part
* of the subkey's public key-pair.
*/
public boolean isNoPassphrase() {
return Key.NO_PASSPHRASE.equals(passphrase);
}

/**
* True if no passphrase is needed to unlock the private part
* of the subkey's public key-pair.
*/
public void setNoPassphrase(boolean x) {
passphrase = x ? Key.NO_PASSPHRASE : "";
}

/**
* Bouncy castle public-key pair,
* containing only the public part of the pair; or null.
Expand Down Expand Up @@ -323,7 +345,7 @@ protected PGPPrivateKey extractPrivateKey(String passphrase)
* Builds a secret key decryptor for the specified passphrase.
*/
protected PBESecretKeyDecryptor buildDecryptor(String passphrase) {
char[] chars = !Util.isEmpty(passphrase) ?
char[] chars = !Util.isEmpty(passphrase) && !isNoPassphrase() ?
passphrase.toCharArray() : new char[0];
return new BcPBESecretKeyDecryptorBuilder(
new BcPGPDigestCalculatorProvider()).build(chars);
Expand Down
15 changes: 15 additions & 0 deletions src/test/groovy/org/c02e/jpgpj/EncryptorSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,21 @@ hQEMAyne546XDHBhAQ...
meta.verified.keys.signingUid == ['Test Key 2 <test-key-2@c02e.org>']
}

def "encrypt and sign with passphrase-less key"() {
when:
def encryptor = new Encryptor(new Ring(stream('test-key-no-passphrase.asc')))
encryptor.ring.keys*.noPassphrase = true
encryptor.encrypt plainIn, cipherOut

def decryptor = new Decryptor(new Ring(stream('test-key-no-passphrase.asc')))
decryptor.ring.keys*.noPassphrase = true
def meta = decryptor.decrypt(cipherIn, plainOut)

then:
plainOut.toString() == plainText
meta.verified
}

def "best packet size"() {
when:
def encryptor = new Encryptor();
Expand Down
34 changes: 34 additions & 0 deletions src/test/resources/test-key-no-passphrase.asc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v1

lgAAAdgEWtE3cAEEANMVepmoansMHh6//w+PeRETdf/k/1zTcHZxqVPpsNLpeHDS
5QJGXxNeGDbozPvu0obG20Qm1D26+CrbhhPHQr/3rPmlQn12SPbjoHkA8/jewcMM
1ABejWf4X6RVYY0xbA6uYU56+a2KkUU4pVFwL2EiuclS0ibjApHFKOYDMIZpABEB
AAEAA/4k7EAoki7kDLPVFakQR/y5qbGNnDk1+89TjKC9qqZRUmEMvTstWXFmkiJC
spiupfEh/bVbl74u+R5RYtpyabvJRr6r0TbyKz17mzF0Z512vryo5yvAkTyuJjoH
5t8/wFk+ENcT9JxBnmr7jJ/R7cyK22J1RJgy9pyf1riLM0Gm7QIA59UxNyypOBh6
7pFADFMDt9RNZI+gUizt7yqbFW4g3dd+ZL8/tXoUrxAXwar+ofpj7NJ6/pNMR4xB
qXhtDA8/9QIA6RaSS8dQoSWhCjvVI4y2PYuyH3qj8mCz2oq/CLYMashbeOv+2Fde
J+RZ+WJXXpzcBybOnYxyvNWS189+DkYoJQH/RMgc1RR+UP3mjzyOM7U/DLZvia5n
A7icnQmBLS3Nw3H0SOG3Q16kLUdNH9Pcq8/jcSJFUfBPcKo3rrRAb6WrIaOytC9O
byBQYXNzcGhyYXNlIDx0ZXN0LWtleS1uby1wYXNzcGhyYXNlQGMwMmUub3JnPoi3
BBMBCAAhBQJa0TdwAhsDBQsJCAcCBhUICQoLAgQWAgMBAh4BAheAAAoJEPQrNY6Y
hh8X+EYEALFpXh22otAoZ5XVsZP7/me0Xi7bcj2xN+/f7wwXXQ0Js22P2s8koR5U
RewLgHHpxbOFmIqL76yda5OJZtsZwOH1alU0CeFviK3m47Htypyx0AUMBEN/1gWC
nKxl0rM+2ofAwAxzrEf0xbjP7/4zt0CUK66nj37Xd/eiJKxPzYIfngAAAdgEWtE3
cAEEAKfRvYix24rYhrVWrTUeaPL74vUFFMOuXIOYJ5463cTKZeQ4ecn072ZtbC/n
hHeV5RGkUu/5GXORR8hPP53/dvm+0fhAP7NfbSMlpfwY1fpoQUVNsVH8CTjNJrSO
AMtS4E/tHIFhhfCN9GV9U8a5/k8uwSTWzpMTdRmktXoa78SzABEBAAEAA/4vElst
8OlqMCLU0Xui9yUr5rA51tOEsa8ccDzImq1iyfy7f4XVuoC+A7pBU5ip7F8EzElB
K2dSrbDrRCNNf38QyQTy7Ugz8QXEOj4BawvpG41jqWn47+Wr6iyiaFz1slXrCXaH
zq/kB8HGcgwjujLk2Vj+1pHFXQ1zDxTlFR3RKQIAy/Kqd+bWziI+7WFgbV5YJsoO
KDNvvbGjc+2xNuUWJ3Yf1suoU90VuSpb0Rx2RnoxmOMDlGawix6nQb12NyTWOwIA
0qaKgUXCMepboXFrr6BviWUfR49+4Zr/B8KcUElER2tBRhwiEqR3ClMXLT3weTea
l2UQ7EbzPVcbVTst7RjL6QH+LKWBoAwI+IVTELA/YpW5Wf8Z2WkPQjYOTqa3sl21
DIDwvUVOguMYAfRo5nFvsU+a7nVe1A6We+S3KZrN/eqYK54ViJ8EGAEIAAkFAlrR
N3ACGwwACgkQ9Cs1jpiGHxcJQgQAvr3BjuacHcFWRzAigi+FILRIvSJk1RrC7S9d
cu1N79GQXeOBRckUja50YkSPQ1IpAR7RV44xeeWDIS0aSNMz6W4snxfAlIsifARf
KZ4ioj0iMMhf83CeuB0Yp46iRStBMPb1EvVeBXBIokLBOKQZq+RJTeMNUwN06fkx
l8nD0Kg=
=Py45
-----END PGP PRIVATE KEY BLOCK-----

0 comments on commit 6a9e298

Please sign in to comment.