mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-27 06:42:05 +01:00
Add method KeyRingInfo.isFullyEncrypted() Fixes #107 Co-authored-by: Ivan Pizhenko <IvanPizhenko@users.noreply.github.com>
This commit is contained in:
parent
0b3511486c
commit
eb47e5caa3
4 changed files with 118 additions and 14 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2021 Flowcrypt a.s. Copyright 2021 Paul Schaub
|
* Copyright 2021 Paul Schaub. Copyright 2021 Flowcrypt a.s.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -77,7 +77,8 @@ public class PGPKeyRingCollection {
|
||||||
pgpPublicKeyRingCollection = new PGPPublicKeyRingCollection(publicKeyRings);
|
pgpPublicKeyRingCollection = new PGPPublicKeyRingCollection(publicKeyRings);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PGPKeyRingCollection(Collection<PGPKeyRing> collection, boolean isSilent) throws IOException, PGPException {
|
public PGPKeyRingCollection(@Nonnull Collection<PGPKeyRing> collection, boolean isSilent)
|
||||||
|
throws IOException, PGPException {
|
||||||
List<PGPSecretKeyRing> secretKeyRings = new ArrayList<>();
|
List<PGPSecretKeyRing> secretKeyRings = new ArrayList<>();
|
||||||
List<PGPPublicKeyRing> publicKeyRings = new ArrayList<>();
|
List<PGPPublicKeyRing> publicKeyRings = new ArrayList<>();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2021 Paul Schaub.
|
* Copyright 2021 Paul Schaub. Copyright 2021 Flowcrypt a.s.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -19,6 +19,7 @@ import org.bouncycastle.bcpg.ECDHPublicBCPGKey;
|
||||||
import org.bouncycastle.bcpg.ECDSAPublicBCPGKey;
|
import org.bouncycastle.bcpg.ECDSAPublicBCPGKey;
|
||||||
import org.bouncycastle.bcpg.ECPublicBCPGKey;
|
import org.bouncycastle.bcpg.ECPublicBCPGKey;
|
||||||
import org.bouncycastle.bcpg.EdDSAPublicBCPGKey;
|
import org.bouncycastle.bcpg.EdDSAPublicBCPGKey;
|
||||||
|
import org.bouncycastle.bcpg.S2K;
|
||||||
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
|
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||||
|
@ -39,6 +40,38 @@ public class KeyInfo {
|
||||||
this.secretKey = null;
|
this.secretKey = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getCurveName() {
|
||||||
|
return getCurveName(publicKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns indication that a contained secret key is encrypted.
|
||||||
|
*
|
||||||
|
* @return true if secret key is encrypted, false if secret key is not encrypted or there is public key only.
|
||||||
|
*/
|
||||||
|
public boolean isEncrypted() {
|
||||||
|
return secretKey != null && isEncrypted(secretKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns indication that a contained secret key is not encrypted.
|
||||||
|
*
|
||||||
|
* @return true if secret key is not encrypted or there is public key only, false if secret key is encrypted.
|
||||||
|
*/
|
||||||
|
public boolean isDecrypted() {
|
||||||
|
return secretKey == null || isDecrypted(secretKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns indication that a contained secret key has S2K of a type GNU_DUMMY_S2K.
|
||||||
|
*
|
||||||
|
* @return true if secret key has S2K of a type GNU_DUMMY_S2K, false if there is public key only,
|
||||||
|
* or S2K on the secret key is absent or not of a type GNU_DUMMY_S2K.
|
||||||
|
*/
|
||||||
|
public boolean hasDummyS2K() {
|
||||||
|
return secretKey != null && hasDummyS2K(secretKey);
|
||||||
|
}
|
||||||
|
|
||||||
public static String getCurveName(PGPPublicKey publicKey) {
|
public static String getCurveName(PGPPublicKey publicKey) {
|
||||||
PublicKeyAlgorithm algorithm = PublicKeyAlgorithm.fromId(publicKey.getAlgorithm());
|
PublicKeyAlgorithm algorithm = PublicKeyAlgorithm.fromId(publicKey.getAlgorithm());
|
||||||
ECPublicBCPGKey key;
|
ECPublicBCPGKey key;
|
||||||
|
@ -64,4 +97,35 @@ public class KeyInfo {
|
||||||
public static String getCurveName(ECPublicBCPGKey key) {
|
public static String getCurveName(ECPublicBCPGKey key) {
|
||||||
return ECUtil.getCurveName(key.getCurveOID());
|
return ECUtil.getCurveName(key.getCurveOID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns indication that a secret key is encrypted.
|
||||||
|
*
|
||||||
|
* @param secretKey A secret key to examine.
|
||||||
|
* @return true if secret key is encrypted, false otherwise.
|
||||||
|
*/
|
||||||
|
public static boolean isEncrypted(PGPSecretKey secretKey) {
|
||||||
|
return secretKey.getS2KUsage() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns indication that a secret key is not encrypted.
|
||||||
|
*
|
||||||
|
* @param secretKey A secret key to examine.
|
||||||
|
* @return true if secret key is encrypted, false otherwise.
|
||||||
|
*/
|
||||||
|
public static boolean isDecrypted(PGPSecretKey secretKey) {
|
||||||
|
return secretKey.getS2KUsage() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns indication that a secret key has S2K of a type GNU_DUMMY_S2K.
|
||||||
|
*
|
||||||
|
* @param secretKey A secret key to examine.
|
||||||
|
* @return true if secret key has S2K of a type GNU_DUMMY_S2K, false otherwise.
|
||||||
|
*/
|
||||||
|
public static boolean hasDummyS2K(PGPSecretKey secretKey) {
|
||||||
|
final S2K s2k = secretKey.getS2K();
|
||||||
|
return s2k != null && s2k.getType() == S2K.GNU_DUMMY_S2K;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2020 Paul Schaub.
|
* Copyright 2020 Paul Schaub. Copyright 2021 Flowcrypt a.s.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -297,16 +297,17 @@ public class KeyRingInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true when every secret key on the key ring is not encrypted.
|
* Returns true when every secret key on the key ring is not encrypted.
|
||||||
* If there is at least one encrypted secret key on the ring, return false.
|
* If there is at least one encrypted secret key on the key ring, returns false.
|
||||||
* If the ring is a {@link PGPPublicKeyRing}, return true.
|
* If the key ring is a {@link PGPPublicKeyRing}, returns true.
|
||||||
|
* Sub-keys with S2K of a type GNU_DUMMY_S2K do not affect the result.
|
||||||
*
|
*
|
||||||
* @return true if all secret keys are unencrypted.
|
* @return true if all secret keys are unencrypted.
|
||||||
*/
|
*/
|
||||||
public boolean isFullyDecrypted() {
|
public boolean isFullyDecrypted() {
|
||||||
if (isSecretKey()) {
|
if (isSecretKey()) {
|
||||||
for (PGPSecretKey secretKey : getSecretKeys()) {
|
for (PGPSecretKey secretKey : getSecretKeys()) {
|
||||||
if (secretKey.getS2KUsage() != 0) {
|
if (!KeyInfo.hasDummyS2K(secretKey) && KeyInfo.isEncrypted(secretKey)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -314,6 +315,26 @@ public class KeyRingInfo {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true when every secret key on the key ring is encrypted.
|
||||||
|
* If there is at least one not encrypted secret key on the key ring, returns false.
|
||||||
|
* If the key ring is a {@link PGPPublicKeyRing}, returns false.
|
||||||
|
* Sub-keys with S2K of a type GNU_DUMMY_S2K do not affect a result.
|
||||||
|
*
|
||||||
|
* @return true if all secret keys are encrypted.
|
||||||
|
*/
|
||||||
|
public boolean isFullyEncrypted() {
|
||||||
|
if (isSecretKey()) {
|
||||||
|
for (PGPSecretKey secretKey : getSecretKeys()) {
|
||||||
|
if (!KeyInfo.hasDummyS2K(secretKey) && KeyInfo.isDecrypted(secretKey)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public List<PGPSignature> getSelfSignaturesOnKey(long subkeyId) {
|
public List<PGPSignature> getSelfSignaturesOnKey(long subkeyId) {
|
||||||
PGPPublicKey publicKey = KeyRingUtils.requirePublicKeyFrom(keys, subkeyId);
|
PGPPublicKey publicKey = KeyRingUtils.requirePublicKeyFrom(keys, subkeyId);
|
||||||
Iterator<PGPSignature> it = publicKey.getSignaturesForKeyID(keys.getPublicKey().getKeyID());
|
Iterator<PGPSignature> it = publicKey.getSignaturesForKeyID(keys.getPublicKey().getKeyID());
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2020 Paul Schaub.
|
* Copyright 2020 Paul Schaub. Copyright 2021 Flowcrypt a.s.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -89,16 +89,34 @@ public class KeyRingInfoTest {
|
||||||
|
|
||||||
assertTrue(info.isFullyDecrypted());
|
assertTrue(info.isFullyDecrypted());
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = encryptSecretKeys(secretKeys);
|
||||||
.changePassphraseFromOldPassphrase(null)
|
|
||||||
.withSecureDefaultSettings()
|
|
||||||
.toNewPassphrase(Passphrase.fromPassword("sw0rdf1sh"))
|
|
||||||
.done();
|
|
||||||
info = PGPainless.inspectKeyRing(secretKeys);
|
info = PGPainless.inspectKeyRing(secretKeys);
|
||||||
|
|
||||||
assertFalse(info.isFullyDecrypted());
|
assertFalse(info.isFullyDecrypted());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsFullyEncrypted() throws IOException, PGPException {
|
||||||
|
PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing();
|
||||||
|
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
||||||
|
|
||||||
|
assertFalse(info.isFullyEncrypted());
|
||||||
|
|
||||||
|
secretKeys = encryptSecretKeys(secretKeys);
|
||||||
|
info = PGPainless.inspectKeyRing(secretKeys);
|
||||||
|
|
||||||
|
assertTrue(info.isFullyEncrypted());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PGPSecretKeyRing encryptSecretKeys(PGPSecretKeyRing secretKeys) throws PGPException {
|
||||||
|
return PGPainless.modifyKeyRing(secretKeys)
|
||||||
|
.changePassphraseFromOldPassphrase(null)
|
||||||
|
.withSecureDefaultSettings()
|
||||||
|
.toNewPassphrase(Passphrase.fromPassword("sw0rdf1sh"))
|
||||||
|
.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetSecretKey() throws IOException, PGPException {
|
public void testGetSecretKey() throws IOException, PGPException {
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing();
|
PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing();
|
||||||
|
|
Loading…
Reference in a new issue