Closed martinedge closed 6 years ago
To get a better understanding:
If this is a bug in the selection logic I'll gladly accept suggestions. For the record (and google) the quote of the mentioned selection logic:
The keys for signing are selected in PGPUtilities lines 123-162. Unfortunately there is no property that marks a key as signing key, just properties for master keys, and encryption keys.
public static PGPPublicKey extractSigningPublicKey(PGPPublicKeyRing keyring) {
// ...
int highestScore = Integer.MIN_VALUE;
for (PGPPublicKey pubKey : keyring) {
int score = calculateSigningKeyScore(pubKey);
if (score > highestScore) {
ret = pubKey;
highestScore = score;
}
}
return ret;
}
/*
* Try to find the best signing key.
* - Try not to use master keys (if possible) because signing should be done with subkeys
* - Give a bonus to "sign only" keys (or 'AUTH' only keys - these are not detected)
*/
private static int calculateSigningKeyScore(PGPPublicKey pubKey) {
int score = 0;
if (!pubKey.isMasterKey()) {
score += 100;
}
if (!pubKey.isEncryptionKey()) {
score += 10;
}
return score;
}
Hey Jens,
The recipient is the one complaining – Everything validates in bouncy castle fine from what I see.
When they review a signing done by a CLI and another by my application;
gpg cli file
gpg --batch --quiet --no-greeting --no-tty --use-agent --decrypt ./emmer-gpg.asc > emmer-gpg.txt
gpg: Signature made Fri Mar 23 10:55:26 2018 AEDT using RSA key ID 724E6B3A
gpg: Good signature from "Emersion Software Systems (Systems key used for external integration) sysadmin@emersion.com.au" [ultimate]
gpg java file
gpg --batch --quiet --no-greeting --no-tty --use-agent --decrypt ./emmer-java.asc > emmer-java.txt
gpg: Signature made Fri Mar 23 10:02:18 2018 AEDT using RSA key ID A41C9878
gpg: WARNING: signing subkey A41C9878 is not cross-certified
gpg: please see https://gnupg.org/faq/subkey-cross-certify.html for more information
gpg: Can't check signature: General error
Yes - I am using RSA keys – I did find the reference in the code you’ve pointed to in PGPUtilities and how you went about this process – What I am curious about is how GPG4Win allegedly believes it knows it is a signing key (and other attributes like authentication) and how it knows that.
I did see in another project whilst trying to understand more about this;
https://justinludwig.github.io/jpgpj/javadoc/org/c02e/jpgpj/Subkey.html - a method called isForSigning()
https://github.com/justinludwig/jpgpj/blob/master/src/main/java/org/c02e/jpgpj/Subkey.java
This looks like an alternative way of ascertaining this?
/**
* Sets forSigning etc flags based on key data.
*/
protected void calculateUsage() throws PGPException {
int flags = getUsageFlags();
boolean canSign = (flags & PGPKeyFlags.CAN_SIGN) ==
PGPKeyFlags.CAN_SIGN;
boolean canEncrypt = ((flags & PGPKeyFlags.CAN_ENCRYPT_COMMS) ==
PGPKeyFlags.CAN_ENCRYPT_COMMS) ||
((flags & PGPKeyFlags.CAN_ENCRYPT_STORAGE) ==
PGPKeyFlags.CAN_ENCRYPT_STORAGE);
forSigning = canSign &&
secretKey != null && !secretKey.isPrivateKeyEmpty();
forVerification = canSign;
forEncryption = canEncrypt;
forDecryption = canEncrypt &&
secretKey != null && !secretKey.isPrivateKeyEmpty();
}
/**
* Usage flags as Bouncy castle {@link PGPKeyFlags} bits.
*/
public int getUsageFlags() throws PGPException {
if (publicKey == null) return 0;
int flags = 0;
// actually only need POSITIVE_CERTIFICATION (for master key)
// and SUBKEY_BINDING (for subkeys)
Iterator<PGPSignature> signatures = publicKey.getSignatures();
while (signatures.hasNext()) {
PGPSignature signature = signatures.next();
PGPSignatureSubpacketVector hashedSubPackets =
signature.getHashedSubPackets();
if (hashedSubPackets != null)
flags |= hashedSubPackets.getKeyFlags();
}
return flags;
}
Thanks for your help! Martin.
From: Jens Neuhalfen [mailto:notifications@github.com] Sent: Friday, 23 March 2018 5:40 PM To: neuhalje/bouncy-gpg bouncy-gpg@noreply.github.com Cc: Martin Edge medge@neverathome.net; Author author@noreply.github.com Subject: Re: [neuhalje/bouncy-gpg] Encryption Key is being selected for signing rather than signing subkey (#16)
To get a better understanding: Who is complaining, and when? My code, bouncy castle or the recipient? I guess you use RSA keys?
For the record (and google) the quote of the mentioned selection logic:
The keys for signing are selected in PGPUtilities https://github.com/neuhalje/bouncy-gpg/blob/master/src/main/java/name/neuhalfen/projects/crypto/bouncycastle/openpgp/keys/PGPUtilities.java#L123-L162 lines 123-162. Unfortunately there is no property that marks a key as signing key, just properties for master keys, and encryption keys.
public static PGPPublicKey extractSigningPublicKey(PGPPublicKeyRing keyring) { // ... int highestScore = Integer.MIN_VALUE; for (PGPPublicKey pubKey : keyring) { int score = calculateSigningKeyScore(pubKey); if (score > highestScore) { ret = pubKey; highestScore = score; } } return ret; }
/*
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/neuhalje/bouncy-gpg/issues/16#issuecomment-375559497 , or mute the thread https://github.com/notifications/unsubscribe-auth/AAiRy7Oq7f3D33XDJH8xp2WUDk0Wfmdkks5thJjWgaJpZM4S4LG_ .
Ugh that formatting is horrible - pro tip don’t reply via email.
Try this;
Hey Jens,
The recipient is the one complaining – Everything validates in bouncy castle fine from what I see.
When they review a signing done by a CLI and another by my application;
gpg cli file gpg --batch --quiet --no-greeting --no-tty --use-agent --decrypt ./emmer-gpg.asc > emmer-gpg.txt gpg: Signature made Fri Mar 23 10:55:26 2018 AEDT using RSA key ID 724E6B3A gpg: Good signature from "Emersion Software Systems (Systems key used for external integration) sysadmin@emersion.com.au" [ultimate]
gpg java file gpg --batch --quiet --no-greeting --no-tty --use-agent --decrypt ./emmer-java.asc > emmer-java.txt gpg: Signature made Fri Mar 23 10:02:18 2018 AEDT using RSA key ID A41C9878 gpg: WARNING: signing subkey A41C9878 is not cross-certified gpg: please see https://gnupg.org/faq/subkey-cross-certify.html for more information gpg: Can't check signature: General error
Yes - I am using RSA keys – I did find the reference in the code you’ve pointed to in PGPUtilities and how you went about this process – What I am curious about is how GPG4Win allegedly believes it knows it is a signing key (and other attributes like authentication) and how it knows that.
I did see in another project whilst trying to understand more about this; https://justinludwig.github.io/jpgpj/javadoc/org/c02e/jpgpj/Subkey.html - a method called isForSigning() https://github.com/justinludwig/jpgpj/blob/master/src/main/java/org/c02e/jpgpj/Subkey.java
This looks like an alternative way of ascertaining this?
/**
Sets forSigning etc flags based on key data. */ protected void calculateUsage() throws PGPException { int flags = getUsageFlags();
boolean canSign = (flags & PGPKeyFlags.CAN_SIGN) ==
PGPKeyFlags.CAN_SIGN;
boolean canEncrypt = ((flags & PGPKeyFlags.CAN_ENCRYPT_COMMS) ==
PGPKeyFlags.CAN_ENCRYPT_COMMS) ||
((flags & PGPKeyFlags.CAN_ENCRYPT_STORAGE) ==
PGPKeyFlags.CAN_ENCRYPT_STORAGE);
forSigning = canSign &&
secretKey != null && !secretKey.isPrivateKeyEmpty();
forVerification = canSign;
forEncryption = canEncrypt;
forDecryption = canEncrypt &&
secretKey != null && !secretKey.isPrivateKeyEmpty();
}
/**
Usage flags as Bouncy castle {@link PGPKeyFlags} bits. */ public int getUsageFlags() throws PGPException { if (publicKey == null) return 0;
int flags = 0;
// actually only need POSITIVE_CERTIFICATION (for master key)
// and SUBKEY_BINDING (for subkeys)
Iterator<PGPSignature> signatures = publicKey.getSignatures();
while (signatures.hasNext()) {
PGPSignature signature = signatures.next();
PGPSignatureSubpacketVector hashedSubPackets =
signature.getHashedSubPackets();
if (hashedSubPackets != null)
flags |= hashedSubPackets.getKeyFlags();
}
return flags;
}
Thanks for your help! Martin.
Hi Martin,
this looks really good! I'll have a look at this this weekend. If it works, I'll prepare a new release
Cheers, Jens
The correct way to determine the key usage is specified in the RFC:
5.2.3.21. Key Flags
(N octets of flags)
This subpacket contains a list of binary flags that hold information about a key. It is a string of octets, and an implementation MUST NOT assume a fixed size. This is so it can grow over time. If a list is shorter than an implementation expects, the unstated flags are considered to be zero. The defined flags are as follows: First octet:
0x01 - This key may be used to certify other keys. 0x02 - This key may be used to sign data. 0x04 - This key may be used to encrypt communications. 0x08 - This key may be used to encrypt storage. 0x10 - The private component of this key may have been split by a secret-sharing mechanism. 0x20 - This key may be used for authentication. 0x80 - The private component of this key may be in the possession of more than one person.
Usage notes:
The flags in this packet may appear in self-signatures or in certification signatures. They mean different things depending on who is making the statement -- for example, a certification signature that has the "sign data" flag is stating that the certification is for that use. On the other hand, the "communications encryption" flag in a self-signature is stating a preference that a given key be used for communications. Note however, that it is a thorny issue to determine what is "communications" and what is "storage". This decision is left wholly up to the implementation; the authors of this document do not claim any special wisdom on the issue and realize that accepted opinion may change.
The "split key" (0x10) and "group key" (0x80) flags are placed on a self-signature only; they are meaningless on a certification signature. They SHOULD be placed only on a direct-key signature (type 0x1F) or a subkey signature (type 0x18), one that refers to the key the flag applies to.
That sounds pretty definitive! :)
On Mar 24, 2018, at 7:57 PM, Jens Neuhalfen notifications@github.com wrote:
The correct way to determine the key usage is specified in the RFC:
5.2.3.21. Key Flags
(N octets of flags)
This subpacket contains a list of binary flags that hold information about a key. It is a string of octets, and an implementation MUST NOT assume a fixed size. This is so it can grow over time. If a list is shorter than an implementation expects, the unstated flags are considered to be zero. The defined flags are as follows: First octet:
0x01 - This key may be used to certify other keys.
0x02 - This key may be used to sign data.
0x04 - This key may be used to encrypt communications.
0x08 - This key may be used to encrypt storage.
0x10 - The private component of this key may have been split by a secret-sharing mechanism.
0x20 - This key may be used for authentication.
0x80 - The private component of this key may be in the possession of more than one person. Usage notes:
The flags in this packet may appear in self-signatures or in certification signatures. They mean different things depending on who is making the statement -- for example, a certification signature that has the "sign data" flag is stating that the certification is for that use. On the other hand, the "communications encryption" flag in a self-signature is stating a preference that a given key be used for communications. Note however, that it is a thorny issue to determine what is "communications" and what is "storage". This decision is left wholly up to the implementation; the authors of this document do not claim any special wisdom on the issue and realize that accepted opinion may change.
The "split key" (0x10) and "group key" (0x80) flags are placed on a self-signature only; they are meaningless on a certification signature. They SHOULD be placed only on a direct-key signature (type 0x1F) or a subkey signature (type 0x18), one that refers to the key the flag applies to.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.
@martinedge Can you please test if this works? (Clone, ./gradlew install
, and then build & test your binary). I did not yet bump the version (and if it works it will 2.2.0 and not 2.0.2 due to minor API changes)
I added a new class Rfc4880KeySelectionStrategy to abstract away all the pesky key selections.
Normally you do not need to change anything. If you want to configure the key selection behavior (e.g. disable expiration checking):
final OutputStream outputStream = BouncyGPG
.encryptToStream()
.withConfig(Configs.keyringConfigFromFilesForSender())
.setReferenceDateForKeyValidityTo(Instant.MIN) // <<-- effectively disable key validity checks
.withAlgorithms(algorithmSuite)
...
This is not yet configurable for decryption
Absolutely! Thanks for doing this – I will give it a go.
Will let you know,
Cheers
Martin.
From: Jens Neuhalfen [mailto:notifications@github.com] Sent: Monday, 26 March 2018 9:17 AM To: neuhalje/bouncy-gpg bouncy-gpg@noreply.github.com Cc: Martin Edge medge@neverathome.net; Mention mention@noreply.github.com Subject: Re: [neuhalje/bouncy-gpg] Encryption Key is being selected for signing rather than signing subkey (#16)
@martinedge https://github.com/martinedge Can you please test if this works? (Clone, ./gradlew install, and then build & test your binary). I did not yet bump the version (and if it works it will 2.2.0 and not 2.0.2 due to minor API changes)
I added a new class Rfc4880KeySelectionStrategy to abstract away all the pesky key selections.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/neuhalje/bouncy-gpg/issues/16#issuecomment-376008185 , or mute the thread https://github.com/notifications/unsubscribe-auth/AAiRy5_f-XEZl6vSDt3le9QZU-qQa98jks5tiBdpgaJpZM4S4LG_ .
Hey Jens,
I've tested the change and it's now reporting that it cannot find the sender UID in the public key ring.
This begs the question as to whether I'm using your library incorrectly - and we've potentially improved detecting but underneath it all I'm actually doing the wrong thing. My expectation is that the encryption and signing process could ascertain what it needed from the private key ring.
My understanding is that we build a key ring config where the public key ring contains the recipients public key and the private key ring contains the senders private key (which would have access to what is required anyway?).
From the look of the selection strategy code you've written it is only interrogating the public key ring in both circumstances for the sender and receiver.
I'm using create from file to build the key rings - do I need to separate create a key ring with the public keys of both sender and receiver?
Here is my key ring config code;
KeyringConfig keyringConfig = null;
if (gpgPrivateKeySenderPassphrase == null || gpgPrivateKeySenderPassphrase.length() < 1L) {
keyringConfig = KeyringConfigs.withKeyRingsFromFiles(new File(gpgPublicKeyreceiverLocation.getPath()), new File(gpgPrivateKeySenderLocation.getPath()), KeyringConfigCallbacks.withUnprotectedKeys());
} else {
keyringConfig = KeyringConfigs.withKeyRingsFromFiles(new File(gpgPublicKeyreceiverLocation.getPath()), new File(gpgPrivateKeySenderLocation.getPath()), KeyringConfigCallbacks.withPassword(gpgPrivateKeySenderPassphrase));
}
... and then I encrypt the file using the following;
OutputStream outputStream = BouncyGPG.encryptToStream().withConfig(keyringConfig).withStrongAlgorithms().toRecipient(gpgPublicKeyReceiverEmail).andSignWith(gpgPrivateKeySenderEmail).armorAsciiOutput().andWriteTo(bufferedOut);
final InputStream is = new FileInputStream(sourcePath+File.separator+inputFilename);
Streams.pipeAll(is, outputStream);
is.close();
outputStream.close();
bufferedOut.close();
also, fyi if I don't close all streams like I'm doing there, the files have no content.
Am I just simply using the library incorrectly? If I am not, I saw in your method that you're grabbing the secret key ring, but not doing anything with it.
final Set<PGPPublicKeyRing> publicKeyrings = this
.publicKeyRingsForUid(purpose, uid, keyringConfig);
final PGPSecretKeyRingCollection secretKeyRings = keyringConfig.getSecretKeyRings();
switch (purpose) {
case FOR_SIGNING:
return publicKeyrings.stream()
.flatMap(keyring -> StreamSupport.stream(keyring.spliterator(), false))
// The master key _can_ be used, but should not. TODO: add some heuristics
// .filter(this::isNotMasterKey)
.filter(this::isVerificationKey)
.filter(this::isNotRevoked)
.filter(this::isNotExpired)
.filter(hasPrivateKey(secretKeyRings))
.reduce((a, b) -> b)
.orElse(null);
case FOR_ENCRYPTION:
return publicKeyrings.stream()
.flatMap(keyring -> StreamSupport.stream(keyring.spliterator(), false))
.filter(this::isEncryptionKey)
.filter(this::isNotRevoked)
.filter(this::isNotExpired)
.reduce((a, b) -> b)
.orElse(null);
default:
return null;
}
Hopefully I'm not just wasting your time! :)
Cheers Martin.
Sorry for the inconvenience, that was a rather largish refactoring/change.
Ok, so the recipient complains? The way you use it seems to be ok. I assume you are running in the Code path that has loaded the private keys? Signing without the Senders private key won‘t work.
Can you
BTW: you can always add the private key file, even if you do not know the password.
OS: no, you are not wasting time. In fact your are contributing to open source 😀👍
On 26. Mar 2018, at 03:56, Martin Edge notifications@github.com wrote:
Hey Jens,
I've tested the change and it's now reporting that it cannot find the sender UID in the public key ring.
This begs the question as to whether I'm using your library incorrectly - and we've potentially improved detecting but underneath it all I'm actually doing the wrong thing. My expectation is that the encryption and signing process could ascertain what it needed from the private key ring.
My understanding is that we build a key ring config where the public key ring contains the recipients public key and the private key ring contains the senders private key (which would have access to what is required anyway?).
From the look of the selection strategy code you've written it is only interrogating the public key ring in both circumstances for the sender and receiver.
I'm using create from file to build the key rings - do I need to separate create a key ring with the public keys of both sender and receiver?
Here is my key ring config code;
KeyringConfig keyringConfig = null; if (gpgPrivateKeySenderPassphrase == null || gpgPrivateKeySenderPassphrase.length() < 1L) { keyringConfig = KeyringConfigs.withKeyRingsFromFiles(new File(gpgPublicKeyreceiverLocation.getPath()), new File(gpgPrivateKeySenderLocation.getPath()), KeyringConfigCallbacks.withUnprotectedKeys()); } else { keyringConfig = KeyringConfigs.withKeyRingsFromFiles(new File(gpgPublicKeyreceiverLocation.getPath()), new File(gpgPrivateKeySenderLocation.getPath()), KeyringConfigCallbacks.withPassword(gpgPrivateKeySenderPassphrase)); }
... and then I encrypt the file using the following;
OutputStream outputStream = BouncyGPG.encryptToStream().withConfig(keyringConfig).withStrongAlgorithms().toRecipient(gpgPublicKeyReceiverEmail).andSignWith(gpgPrivateKeySenderEmail).armorAsciiOutput().andWriteTo(bufferedOut); final InputStream is = new FileInputStream(sourcePath+File.separator+inputFilename); Streams.pipeAll(is, outputStream); is.close(); outputStream.close(); bufferedOut.close();
also, fyi if I don't close all streams like I'm doing there, the files have no content.
Am I just simply using the library incorrectly? If I am not, I saw in your method that you're grabbing the secret key ring, but not doing anything with it.
final Set
publicKeyrings = this .publicKeyRingsForUid(purpose, uid, keyringConfig); final PGPSecretKeyRingCollection secretKeyRings = keyringConfig.getSecretKeyRings(); switch (purpose) { case FOR_SIGNING: return publicKeyrings.stream() .flatMap(keyring -> StreamSupport.stream(keyring.spliterator(), false)) // The master key _can_ be used, but should not. TODO: add some heuristics // .filter(this::isNotMasterKey) .filter(this::isVerificationKey) .filter(this::isNotRevoked) .filter(this::isNotExpired) .filter(hasPrivateKey(secretKeyRings)) .reduce((a, b) -> b) .orElse(null); case FOR_ENCRYPTION: return publicKeyrings.stream() .flatMap(keyring -> StreamSupport.stream(keyring.spliterator(), false)) .filter(this::isEncryptionKey) .filter(this::isNotRevoked) .filter(this::isNotExpired) .reduce((a, b) -> b) .orElse(null); default: return null; }
Hopefully I'm not just wasting your time! :)
Cheers Martin.
— You are receiving this because you were assigned. Reply to this email directly, view it on GitHub, or mute the thread.
Hey Jens,
No - your library complains that it is unable to find the senders public key for signature.
I am using the public key from the receiver for the first parameter of the key ring method. I am using my private key for second parameter for the key ring method (to sign and encrypt).
:user ID packet: "ipnd-iis (IPND IIS file transfer encryption key.) <ipnd-iis@ipnd.com.au>"
# off=346 ctb=89 tag=2 hlen=3 plen=313
:signature packet: algo 1, keyid 460F8D7C5BC59835
version 4, created 1516751828, md5len 0, sigclass 0x13
digest algo 8, begin of digest a0 ac
hashed subpkt 2 len 4 (sig created 2018-01-23)
hashed subpkt 27 len 1 (key flags: 03)
hashed subpkt 11 len 6 (pref-sym-algos: 9 8 7 3 2 1)
hashed subpkt 21 len 5 (pref-hash-algos: 8 2 9 10 11)
hashed subpkt 22 len 3 (pref-zip-algos: 2 3 1)
hashed subpkt 30 len 1 (features: 01)
hashed subpkt 23 len 1 (keyserver preferences: 80)
subpkt 16 len 8 (issuer key ID 460F8D7C5BC59835)
data: [2047 bits]
# off=662 ctb=b9 tag=14 hlen=3 plen=269
:public sub key packet:
version 4, algo 1, created 1516751828, expires 0
pkey[0]: [2048 bits]
pkey[1]: [17 bits]
keyid: B239EE64FBFA9B6E
# off=934 ctb=89 tag=2 hlen=3 plen=287
:signature packet: algo 1, keyid 460F8D7C5BC59835
version 4, created 1516751828, md5len 0, sigclass 0x18
digest algo 8, begin of digest 59 80
hashed subpkt 2 len 4 (sig created 2018-01-23)
hashed subpkt 27 len 1 (key flags: 0C)
subpkt 16 len 8 (issuer key ID 460F8D7C5BC59835)
data: [2047 bits]
pub rsa2048 2018-01-23 [SC]
CD4C04C9630DAD81B192A1BC460F8D7C5BC59835
uid ipnd-iis (IPND IIS file transfer encryption key.) <ipnd-iis@ipnd.com.au>
sig 460F8D7C5BC59835 2018-01-23 [selfsig]
sub rsa2048 2018-01-23 [E]
sig 460F8D7C5BC59835 2018-01-23 [keybind]
I guess my query is then - when it comes to ascertaining whether it has a keyring with the sender UID in it, should it be calling this method 'selectPublicKey' - to check the keys or should it be doing this task on the private key which is doing the encryption?
Happy to help with attempting to work through the issue - but I haven't used gradle before so unsure how to get the project building within Eclipse. Would then be able to debug exactly what is happening.
I'll have a fiddle with it tonight to see if I can get the dependencies downloaded and put in the build path.
Cheers Martin.
I tried the following and it works 'kind of'. I think I the issue is a borked expiry check but the train is arriving at my $DAYJOB in 2 minutes. I'll look into this tonight ("Europe tonight" ;-) ).
note: Key 0x83063C3DA3814052 will expire today. So my gpg CLI will happily accept it.
I tried the following and found out that the signature is made with the expired key: The message Signature made Mon Mar 26 08:37:10 2018 CEST ... using RSA key 0x83063C3DA3814052
.
Do your keys have an expiry date? If yes, that maybe I just inverted the check for expiring keys :-(
@Test
public void issue16works()
throws IOException, PGPException, NoSuchAlgorithmException, NoSuchProviderException, SignatureException {
final byte[] expectedPlaintext = ExampleMessages.IMPORTANT_QUOTE_TEXT.getBytes("US-ASCII");
byte[] bytes;
try (
final ByteArrayInputStream is = new ByteArrayInputStream(expectedPlaintext);
final ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
final OutputStream outputStream = BouncyGPG
.encryptToStream()
.withConfig(RFC4880TestKeyrings.publicAndPrivateKeyKeyringConfig())
.withStrongAlgorithms()
.toRecipient("rfc4880@example.org")
.andSignWith("rfc4880@example.org")
.armorAsciiOutput()
.andWriteTo(byteOutput)
) {
Streams.pipeAll(is, outputStream);
outputStream.close();
bytes = byteOutput.toByteArray();
}
final String ciphertext = new String(bytes,"US-ASCII");
System.out.println(
"This should be to 'rfc4880@example.org' and also signed by 'rfc4880@example.org'\n\n"
+ ciphertext);
}
Which gives me
This should be to 'rfc4880@example.org' and also signed by 'rfc4880@example.org'
-----BEGIN PGP MESSAGE-----
Version: BCPG v1.58
hQEMA0c3f+3RbCazAQf+Kbu00zT3NKigdQNTiGl2O6uNfM/5KRxqMn43HCABXQkj
OQZmRB4DGSrD525IdXR9e4v5tuSK/oMTos76qKwfzEXENixdLoJhmxBGAO0pv/4x
C6PM3f0bVib3RQE7yXS/wz/9nI3Hk5TVh+8y5dL8fsfYjG8eJXLIcbLWwbZFwq9u
1WR3t9I4N3Zx4fZig6eEYjZYk6eYFKlLUtGdGDJr0kpXXHf6b2sMjL6Zk9HjePBR
i+otmhU8PR1XZfVl0+AmlEvmvRGFHPIrmwhQ4D86FccTXYlE8w3tllt9I4aDh/JE
UXZYK82Sc0c8l8MDjWcWIMk9s9xm/dm0Dp7zG9HN49LA+gEBFi3b6UEPRbykSAIS
IZiihRHhFT9XLjWdyzsNKD5xlTVWe+dR2psmixGFkrv1YMYeNUBQi5B0J2AeoHSG
rniWJu1wBZiij9MvX1cXMho40qWYJkEQt0JfiYIpUHhMgiZNLCTYYpv7tQzLCDK1
+cQt7g0UWWx9WXHTQs2r+CWKI1z5YIM1qZh57uBWtswFP3yKINetVOtaZHkhlq1M
OUGJ7rAiSEQaKD+dzJWo69fKZc/FTHm6vgfg1h4QNieR5PSBm/OlbGQKU0aEW36w
2GzOhoyQu8ZSVFTiklD0WH+ZOjAYPqNc/+jrFOeKJSCJ6rQcwYCRvDIhb+fimaCV
i180zIcPORPQETADtkVpLWsGte1YTaA8t7Oz/dsjYjD80S2R+EIfDN968dWXsiuW
yPhGbkLQpe8k3QU+DpGvw8I2xiERHcw5NGjIQ82yDZ71brkXTRGrsujzxz0DHDsN
IbB+cva7QSav4W6mWlar+9yVMjsAyzI3Aw+k58A1d2OZvbM4lqfve6TsCQ56q3OZ
xfAaR3gTb3DClyjUed4B4UegXcHHXOvlYQaWoQqfJqx9LP5+g0IQfULkE5g=
=ld6j
-----END PGP MESSAGE-----
I have imported the public/private keys from the test keyrings in my local gpp.
Running
echo '-----BEGIN PGP MESSAGE-----
Version: BCPG v1.58
...
-----END PGP MESSAGE-----' | gpg -d -v
Successfully gives me
gpg: armor header: Version: BCPG v1.58
gpg: public key is 0x47377FEDD16C26B3
gpg: Note: signature key 0xDFAAFD6855BAAF35 has been revoked
gpg: using subkey 0x47377FEDD16C26B3 instead of primary key 0xF8BEA74E37D9F45D
gpg: Note: signature key 0xDFAAFD6855BAAF35 has been revoked
gpg: Note: signature key 0xDFAAFD6855BAAF35 has been revoked
gpg: using subkey 0x47377FEDD16C26B3 instead of primary key 0xF8BEA74E37D9F45D
gpg: encrypted with 2048-bit RSA key, ID 0x47377FEDD16C26B3, created 2018-03-25
"RFC4880 Test User <rfc4880@example.org>"
gpg: AES encrypted data
gpg: original file name=''
I love deadlines. I like the whooshing sound they make as they fly by. Douglas Adamsgpg: Signature made Mon Mar 26 08:51:33 2018 CEST
gpg: using RSA key 0x83063C3DA3814052
gpg: Note: signature key 0xDFAAFD6855BAAF35 has been revoked
gpg: using subkey 0x83063C3DA3814052 instead of primary key 0xF8BEA74E37D9F45D
gpg: Note: signature key 0xDFAAFD6855BAAF35 has been revoked
gpg: using pgp trust model
gpg: Good signature from "RFC4880 Test User <rfc4880@example.org>" [ultimate]
gpg: Note: signature key 0xDFAAFD6855BAAF35 has been revoked
gpg: binary signature, digest algorithm SHA256, key algorithm rsa2048
The signature is made by key 0x83063C3DA3814052 which is the expired key (this is indeed a bug!)
I have gpg 2.2.3 installed:
# gpg --version
gpg (GnuPG/MacGPG2) 2.2.3
libgcrypt 1.8.1
...
Interesting! Well, the public key part of the process I believe the code is performing fine. (does not (at least I think) have an expired portion.).
It's actually when validating the sender (sysadmin@emersion.com.au) it's attempting to find it in the public key ring.
I think I've managed to get gradle working with this project, so if I can debug I may be able to provide more information.
Have a great day!
Whilst we work through this - we can work on email if you want - medge at neverathome.net :)
I have send you an e-mail
Issue is resolved. Primarily my fault in misunderstanding that the signers public key needs to be loaded in the public key ring also - but hey, we made an improvement nonetheless!
Thanks Jens!
Martin
When encrypting and signing a file, I'm getting complaints that the encryption key is being used to sign.
I can see code in the source that suggests there has been attempted provisions to get the correct sub key, but I am not sure it is being used in this circumstance.
I have regenerated keys just in case to no avail.
Are there any special tricks to ensure the correct subkey is used for the signing process?