mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-22 20:32:05 +01:00
Make KO-countermeasures configurable (off by default)
This commit is contained in:
parent
cfba77dea5
commit
bfbaa30e4c
3 changed files with 39 additions and 1 deletions
|
@ -9,6 +9,7 @@ import org.bouncycastle.openpgp.PGPException;
|
|||
import org.bouncycastle.openpgp.PGPPrivateKey;
|
||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||
import org.pgpainless.PGPainless;
|
||||
import org.pgpainless.exception.KeyIntegrityException;
|
||||
import org.pgpainless.exception.WrongPassphraseException;
|
||||
import org.pgpainless.key.info.KeyInfo;
|
||||
|
@ -51,7 +52,9 @@ public final class UnlockSecretKey {
|
|||
throw new PGPException("Cannot decrypt secret key.");
|
||||
}
|
||||
|
||||
PublicKeyParameterValidationUtil.verifyPublicKeyParameterIntegrity(privateKey, secretKey.getPublicKey());
|
||||
if (PGPainless.getPolicy().isEnableKeyParameterValidation()) {
|
||||
PublicKeyParameterValidationUtil.verifyPublicKeyParameterIntegrity(privateKey, secretKey.getPublicKey());
|
||||
}
|
||||
|
||||
return privateKey;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,8 @@ public final class Policy {
|
|||
// Signers User-ID is soon to be deprecated.
|
||||
private SignerUserIdValidationLevel signerUserIdValidationLevel = SignerUserIdValidationLevel.DISABLED;
|
||||
|
||||
private boolean enableKeyParameterValidation = false;
|
||||
|
||||
public enum SignerUserIdValidationLevel {
|
||||
/**
|
||||
* PGPainless will verify {@link org.bouncycastle.bcpg.sig.SignerUserID} subpackets in signatures strictly.
|
||||
|
@ -701,4 +703,31 @@ public final class Policy {
|
|||
this.signerUserIdValidationLevel = signerUserIdValidationLevel;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable validation of public key parameters when unlocking private keys.
|
||||
* Disabled by default.
|
||||
* When enabled, PGPainless will validate, whether public key parameters have been tampered with.
|
||||
* This is a countermeasure against possible attacks described in the paper
|
||||
* "Victory by KO: Attacking OpenPGP Using Key Overwriting" by Lara Bruseghini, Daniel Huigens, and Kenneth G. Paterson.
|
||||
* Since these attacks are only possible in very special conditions (attacker has access to the encrypted private key),
|
||||
* and the countermeasures are very costly, they are disabled by default, but can be enabled using this method.
|
||||
*
|
||||
* @see <a href="https://www.kopenpgp.com/#paper">KOpenPGP.com</a>
|
||||
* @param enable boolean
|
||||
* @return this
|
||||
*/
|
||||
public Policy setEnableKeyParameterValidation(boolean enable) {
|
||||
this.enableKeyParameterValidation = enable;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true, if countermeasures against the KOpenPGP attacks are enabled, false otherwise.
|
||||
*
|
||||
* @return true if countermeasures are enabled, false otherwise.
|
||||
*/
|
||||
public boolean isEnableKeyParameterValidation() {
|
||||
return enableKeyParameterValidation;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -212,10 +212,12 @@ public class ModifiedPublicKeysInvestigation {
|
|||
SecretKeyRingProtector protector = SecretKeyRingProtector.unlockAnyKeyWith(Passphrase.fromPassword("12345678"));
|
||||
PGPSecretKeyRing dsa = PGPainless.readKeyRing().secretKeyRing(DSA);
|
||||
|
||||
PGPainless.getPolicy().setEnableKeyParameterValidation(true);
|
||||
assertThrows(KeyIntegrityException.class, () ->
|
||||
UnlockSecretKey.unlockSecretKey(dsa.getSecretKey(KeyIdUtil.fromLongKeyId("b1bd1f049ec87f3d")), protector));
|
||||
assertThrows(KeyIntegrityException.class, () ->
|
||||
UnlockSecretKey.unlockSecretKey(dsa.getSecretKey(KeyIdUtil.fromLongKeyId("f5ffdf6d71dd5789")), protector));
|
||||
PGPainless.getPolicy().setEnableKeyParameterValidation(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -223,8 +225,10 @@ public class ModifiedPublicKeysInvestigation {
|
|||
SecretKeyRingProtector protector = SecretKeyRingProtector.unlockAnyKeyWith(Passphrase.fromPassword("12345678"));
|
||||
PGPSecretKeyRing elgamal = PGPainless.readKeyRing().secretKeyRing(ELGAMAL);
|
||||
|
||||
PGPainless.getPolicy().setEnableKeyParameterValidation(true);
|
||||
assertThrows(KeyIntegrityException.class, () ->
|
||||
UnlockSecretKey.unlockSecretKey(elgamal.getSecretKey(KeyIdUtil.fromLongKeyId("f5ffdf6d71dd5789")), protector));
|
||||
PGPainless.getPolicy().setEnableKeyParameterValidation(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -232,8 +236,10 @@ public class ModifiedPublicKeysInvestigation {
|
|||
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(INJECTED_KEY);
|
||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unlockAnyKeyWith(Passphrase.fromPassword("pass"));
|
||||
|
||||
PGPainless.getPolicy().setEnableKeyParameterValidation(true);
|
||||
assertThrows(KeyIntegrityException.class, () ->
|
||||
UnlockSecretKey.unlockSecretKey(secretKeys.getSecretKey(), protector));
|
||||
PGPainless.getPolicy().setEnableKeyParameterValidation(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in a new issue