mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-23 11:27:57 +01:00
Implement certifying of certifications
This commit is contained in:
parent
fa5ddfd112
commit
d2b48e83d9
8 changed files with 277 additions and 31 deletions
|
@ -10,8 +10,8 @@ public class Trustworthiness {
|
||||||
private final int depth;
|
private final int depth;
|
||||||
|
|
||||||
public static final int THRESHOLD_FULLY_CONVINCED = 120;
|
public static final int THRESHOLD_FULLY_CONVINCED = 120;
|
||||||
public static final int THRESHOLD_MARGINALLY_CONVINCED = 60;
|
public static final int MARGINALLY_CONVINCED = 60;
|
||||||
public static final int THRESHOLD_NOT_TRUSTED = 0;
|
public static final int NOT_TRUSTED = 0;
|
||||||
|
|
||||||
public Trustworthiness(int amount, int depth) {
|
public Trustworthiness(int amount, int depth) {
|
||||||
this.amount = capAmount(amount);
|
this.amount = capAmount(amount);
|
||||||
|
@ -26,6 +26,30 @@ public class Trustworthiness {
|
||||||
return depth;
|
return depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isNotTrusted() {
|
||||||
|
return getAmount() == NOT_TRUSTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMarginallyTrusted() {
|
||||||
|
return getAmount() > NOT_TRUSTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFullyTrusted() {
|
||||||
|
return getAmount() >= THRESHOLD_FULLY_CONVINCED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isIntroducer() {
|
||||||
|
return getDepth() >= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canIntroduce(int otherDepth) {
|
||||||
|
return getDepth() > otherDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canIntroduce(Trustworthiness other) {
|
||||||
|
return canIntroduce(other.getDepth());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This means that we are fully convinced of the trustworthiness of the key.
|
* This means that we are fully convinced of the trustworthiness of the key.
|
||||||
*
|
*
|
||||||
|
@ -41,7 +65,7 @@ public class Trustworthiness {
|
||||||
* @return builder
|
* @return builder
|
||||||
*/
|
*/
|
||||||
public static Builder marginallyTrusted() {
|
public static Builder marginallyTrusted() {
|
||||||
return new Builder(THRESHOLD_MARGINALLY_CONVINCED);
|
return new Builder(MARGINALLY_CONVINCED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,7 +75,7 @@ public class Trustworthiness {
|
||||||
* @return builder
|
* @return builder
|
||||||
*/
|
*/
|
||||||
public static Builder untrusted() {
|
public static Builder untrusted() {
|
||||||
return new Builder(THRESHOLD_NOT_TRUSTED);
|
return new Builder(NOT_TRUSTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class Builder {
|
public static final class Builder {
|
||||||
|
|
|
@ -19,7 +19,7 @@ import org.pgpainless.key.OpenPgpFingerprint;
|
||||||
import org.pgpainless.key.info.KeyRingInfo;
|
import org.pgpainless.key.info.KeyRingInfo;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
import org.pgpainless.key.util.KeyRingUtils;
|
import org.pgpainless.key.util.KeyRingUtils;
|
||||||
import org.pgpainless.signature.builder.DirectKeySignatureBuilder;
|
import org.pgpainless.signature.builder.ThirdPartyDirectKeySignatureBuilder;
|
||||||
import org.pgpainless.signature.builder.ThirdPartyCertificationSignatureBuilder;
|
import org.pgpainless.signature.builder.ThirdPartyCertificationSignatureBuilder;
|
||||||
import org.pgpainless.signature.subpackets.CertificationSubpackets;
|
import org.pgpainless.signature.subpackets.CertificationSubpackets;
|
||||||
import org.pgpainless.util.DateUtil;
|
import org.pgpainless.util.DateUtil;
|
||||||
|
@ -28,20 +28,60 @@ import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API for creating certifications and delegations (Signatures) on keys.
|
||||||
|
* This API can be used to sign another persons OpenPGP key.
|
||||||
|
*
|
||||||
|
* A certification over a user-id is thereby used to attest, that the user believes that the user-id really belongs
|
||||||
|
* to the owner of the certificate.
|
||||||
|
* A delegation over a key can be used to delegate trust by marking the certificate as a trusted introducer.
|
||||||
|
*/
|
||||||
public class CertifyCertificate {
|
public class CertifyCertificate {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a certification over a User-Id.
|
||||||
|
* By default, this method will use {@link CertificationType#GENERIC} to create the signature.
|
||||||
|
* If you need to create another type of certification, use
|
||||||
|
* {@link #userIdOnCertificate(String, PGPPublicKeyRing, CertificationType)} instead.
|
||||||
|
*
|
||||||
|
* @param userId user-id to certify
|
||||||
|
* @param certificate certificate
|
||||||
|
* @return API
|
||||||
|
*/
|
||||||
CertificationOnUserId userIdOnCertificate(@Nonnull String userId, @Nonnull PGPPublicKeyRing certificate) {
|
CertificationOnUserId userIdOnCertificate(@Nonnull String userId, @Nonnull PGPPublicKeyRing certificate) {
|
||||||
return new CertificationOnUserId(userId, certificate, CertificationType.GENERIC);
|
return new CertificationOnUserId(userId, certificate, CertificationType.GENERIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a certification of the given {@link CertificationType} over a User-Id.
|
||||||
|
*
|
||||||
|
* @param userid user-id to certify
|
||||||
|
* @param certificate certificate
|
||||||
|
* @param certificationType type of signature
|
||||||
|
* @return API
|
||||||
|
*/
|
||||||
CertificationOnUserId userIdOnCertificate(@Nonnull String userid, @Nonnull PGPPublicKeyRing certificate, @Nonnull CertificationType certificationType) {
|
CertificationOnUserId userIdOnCertificate(@Nonnull String userid, @Nonnull PGPPublicKeyRing certificate, @Nonnull CertificationType certificationType) {
|
||||||
return new CertificationOnUserId(userid, certificate, certificationType);
|
return new CertificationOnUserId(userid, certificate, certificationType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a delegation (direct key signature) over a certificate.
|
||||||
|
*
|
||||||
|
* @param certificate certificate
|
||||||
|
* @return API
|
||||||
|
*/
|
||||||
DelegationOnCertificate certificate(@Nonnull PGPPublicKeyRing certificate) {
|
DelegationOnCertificate certificate(@Nonnull PGPPublicKeyRing certificate) {
|
||||||
return certificate(certificate, null);
|
return certificate(certificate, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a delegation (direct key signature) containing a {@link org.bouncycastle.bcpg.sig.TrustSignature} packet
|
||||||
|
* over a certificate.
|
||||||
|
*
|
||||||
|
* @param certificate certificate
|
||||||
|
* @param trustworthiness trustworthiness of the certificate
|
||||||
|
* @return API
|
||||||
|
*/
|
||||||
DelegationOnCertificate certificate(@Nonnull PGPPublicKeyRing certificate, @Nullable Trustworthiness trustworthiness) {
|
DelegationOnCertificate certificate(@Nonnull PGPPublicKeyRing certificate, @Nullable Trustworthiness trustworthiness) {
|
||||||
return new DelegationOnCertificate(certificate, trustworthiness);
|
return new DelegationOnCertificate(certificate, trustworthiness);
|
||||||
}
|
}
|
||||||
|
@ -58,8 +98,16 @@ public class CertifyCertificate {
|
||||||
this.certificationType = certificationType;
|
this.certificationType = certificationType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the certification using the given key.
|
||||||
|
*
|
||||||
|
* @param certificationKey key used to create the certification
|
||||||
|
* @param protector protector to unlock the certification key
|
||||||
|
* @return API
|
||||||
|
* @throws PGPException in case of an OpenPGP related error
|
||||||
|
*/
|
||||||
CertificationOnUserIdWithSubpackets withKey(@Nonnull PGPSecretKeyRing certificationKey, @Nonnull SecretKeyRingProtector protector) throws PGPException {
|
CertificationOnUserIdWithSubpackets withKey(@Nonnull PGPSecretKeyRing certificationKey, @Nonnull SecretKeyRingProtector protector) throws PGPException {
|
||||||
PGPSecretKey secretKey = getCertificationSecretKey(certificationKey);
|
PGPSecretKey secretKey = getCertifyingSecretKey(certificationKey);
|
||||||
|
|
||||||
ThirdPartyCertificationSignatureBuilder sigBuilder = new ThirdPartyCertificationSignatureBuilder(
|
ThirdPartyCertificationSignatureBuilder sigBuilder = new ThirdPartyCertificationSignatureBuilder(
|
||||||
certificationType.asSignatureType(), secretKey, protector);
|
certificationType.asSignatureType(), secretKey, protector);
|
||||||
|
@ -80,11 +128,24 @@ public class CertifyCertificate {
|
||||||
this.sigBuilder = sigBuilder;
|
this.sigBuilder = sigBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CertificationResult withSubpackets(@Nonnull CertificationSubpackets.Callback subpacketCallback) throws PGPException {
|
/**
|
||||||
|
* Apply the given signature subpackets and build the certification.
|
||||||
|
*
|
||||||
|
* @param subpacketCallback callback to modify the signatures subpackets
|
||||||
|
* @return result
|
||||||
|
* @throws PGPException in case of an OpenPGP related error
|
||||||
|
*/
|
||||||
|
public CertificationResult buildWithSubpackets(@Nonnull CertificationSubpackets.Callback subpacketCallback) throws PGPException {
|
||||||
sigBuilder.applyCallback(subpacketCallback);
|
sigBuilder.applyCallback(subpacketCallback);
|
||||||
return build();
|
return build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the certification signature.
|
||||||
|
*
|
||||||
|
* @return result
|
||||||
|
* @throws PGPException in case of an OpenPGP related error
|
||||||
|
*/
|
||||||
public CertificationResult build() throws PGPException {
|
public CertificationResult build() throws PGPException {
|
||||||
PGPSignature signature = sigBuilder.build(certificate, userId);
|
PGPSignature signature = sigBuilder.build(certificate, userId);
|
||||||
PGPPublicKeyRing certifiedCertificate = KeyRingUtils.injectCertification(certificate, userId, signature);
|
PGPPublicKeyRing certifiedCertificate = KeyRingUtils.injectCertification(certificate, userId, signature);
|
||||||
|
@ -102,10 +163,18 @@ public class CertifyCertificate {
|
||||||
this.trustworthiness = trustworthiness;
|
this.trustworthiness = trustworthiness;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the delegation using the given certification key.
|
||||||
|
*
|
||||||
|
* @param certificationKey key to create the certification with
|
||||||
|
* @param protector protector to unlock the certification key
|
||||||
|
* @return API
|
||||||
|
* @throws PGPException in case of an OpenPGP related error
|
||||||
|
*/
|
||||||
public DelegationOnCertificateWithSubpackets withKey(@Nonnull PGPSecretKeyRing certificationKey, @Nonnull SecretKeyRingProtector protector) throws PGPException {
|
public DelegationOnCertificateWithSubpackets withKey(@Nonnull PGPSecretKeyRing certificationKey, @Nonnull SecretKeyRingProtector protector) throws PGPException {
|
||||||
PGPSecretKey secretKey = getCertificationSecretKey(certificationKey);
|
PGPSecretKey secretKey = getCertifyingSecretKey(certificationKey);
|
||||||
|
|
||||||
DirectKeySignatureBuilder sigBuilder = new DirectKeySignatureBuilder(secretKey, protector);
|
ThirdPartyDirectKeySignatureBuilder sigBuilder = new ThirdPartyDirectKeySignatureBuilder(secretKey, protector);
|
||||||
if (trustworthiness != null) {
|
if (trustworthiness != null) {
|
||||||
sigBuilder.getHashedSubpackets().setTrust(true, trustworthiness.getDepth(), trustworthiness.getAmount());
|
sigBuilder.getHashedSubpackets().setTrust(true, trustworthiness.getDepth(), trustworthiness.getAmount());
|
||||||
}
|
}
|
||||||
|
@ -116,18 +185,31 @@ public class CertifyCertificate {
|
||||||
public static class DelegationOnCertificateWithSubpackets {
|
public static class DelegationOnCertificateWithSubpackets {
|
||||||
|
|
||||||
private final PGPPublicKeyRing certificate;
|
private final PGPPublicKeyRing certificate;
|
||||||
private final DirectKeySignatureBuilder sigBuilder;
|
private final ThirdPartyDirectKeySignatureBuilder sigBuilder;
|
||||||
|
|
||||||
public DelegationOnCertificateWithSubpackets(@Nonnull PGPPublicKeyRing certificate, @Nonnull DirectKeySignatureBuilder sigBuilder) {
|
DelegationOnCertificateWithSubpackets(@Nonnull PGPPublicKeyRing certificate, @Nonnull ThirdPartyDirectKeySignatureBuilder sigBuilder) {
|
||||||
this.certificate = certificate;
|
this.certificate = certificate;
|
||||||
this.sigBuilder = sigBuilder;
|
this.sigBuilder = sigBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CertificationResult withSubpackets(@Nonnull CertificationSubpackets.Callback subpacketsCallback) throws PGPException {
|
/**
|
||||||
|
* Apply the given signature subpackets and build the delegation signature.
|
||||||
|
*
|
||||||
|
* @param subpacketsCallback callback to modify the signatures subpackets
|
||||||
|
* @return result
|
||||||
|
* @throws PGPException in case of an OpenPGP related error
|
||||||
|
*/
|
||||||
|
public CertificationResult buildWithSubpackets(@Nonnull CertificationSubpackets.Callback subpacketsCallback) throws PGPException {
|
||||||
sigBuilder.applyCallback(subpacketsCallback);
|
sigBuilder.applyCallback(subpacketsCallback);
|
||||||
return build();
|
return build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the delegation signature.
|
||||||
|
*
|
||||||
|
* @return result
|
||||||
|
* @throws PGPException in case of an OpenPGP related error
|
||||||
|
*/
|
||||||
public CertificationResult build() throws PGPException {
|
public CertificationResult build() throws PGPException {
|
||||||
PGPPublicKey delegatedKey = certificate.getPublicKey();
|
PGPPublicKey delegatedKey = certificate.getPublicKey();
|
||||||
PGPSignature delegation = sigBuilder.build(delegatedKey);
|
PGPSignature delegation = sigBuilder.build(delegatedKey);
|
||||||
|
@ -146,18 +228,28 @@ public class CertifyCertificate {
|
||||||
this.certification = certification;
|
this.certification = certification;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the signature.
|
||||||
|
*
|
||||||
|
* @return signature
|
||||||
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public PGPSignature getCertification() {
|
public PGPSignature getCertification() {
|
||||||
return certification;
|
return certification;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the certificate, which now contains the signature.
|
||||||
|
*
|
||||||
|
* @return certificate + signature
|
||||||
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public PGPPublicKeyRing getCertifiedCertificate() {
|
public PGPPublicKeyRing getCertifiedCertificate() {
|
||||||
return certificate;
|
return certificate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PGPSecretKey getCertificationSecretKey(PGPSecretKeyRing certificationKey) {
|
private static PGPSecretKey getCertifyingSecretKey(PGPSecretKeyRing certificationKey) {
|
||||||
Date now = DateUtil.now();
|
Date now = DateUtil.now();
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(certificationKey, now);
|
KeyRingInfo info = PGPainless.inspectKeyRing(certificationKey, now);
|
||||||
|
|
||||||
|
@ -179,5 +271,4 @@ public class CertifyCertificate {
|
||||||
}
|
}
|
||||||
return secretKey;
|
return secretKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,10 +56,9 @@ import org.pgpainless.key.protection.fixes.S2KUsageFix;
|
||||||
import org.pgpainless.key.protection.passphrase_provider.SolitaryPassphraseProvider;
|
import org.pgpainless.key.protection.passphrase_provider.SolitaryPassphraseProvider;
|
||||||
import org.pgpainless.key.util.KeyRingUtils;
|
import org.pgpainless.key.util.KeyRingUtils;
|
||||||
import org.pgpainless.key.util.RevocationAttributes;
|
import org.pgpainless.key.util.RevocationAttributes;
|
||||||
import org.pgpainless.signature.builder.DirectKeySignatureBuilder;
|
import org.pgpainless.signature.builder.DirectKeySelfSignatureBuilder;
|
||||||
import org.pgpainless.signature.builder.RevocationSignatureBuilder;
|
import org.pgpainless.signature.builder.RevocationSignatureBuilder;
|
||||||
import org.pgpainless.signature.builder.SelfSignatureBuilder;
|
import org.pgpainless.signature.builder.SelfSignatureBuilder;
|
||||||
import org.pgpainless.signature.subpackets.CertificationSubpackets;
|
|
||||||
import org.pgpainless.signature.subpackets.RevocationSignatureSubpackets;
|
import org.pgpainless.signature.subpackets.RevocationSignatureSubpackets;
|
||||||
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets;
|
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets;
|
||||||
import org.pgpainless.signature.subpackets.SignatureSubpackets;
|
import org.pgpainless.signature.subpackets.SignatureSubpackets;
|
||||||
|
@ -613,12 +612,10 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
|
||||||
PGPPublicKey publicKey = primaryKey.getPublicKey();
|
PGPPublicKey publicKey = primaryKey.getPublicKey();
|
||||||
final Date keyCreationTime = publicKey.getCreationTime();
|
final Date keyCreationTime = publicKey.getCreationTime();
|
||||||
|
|
||||||
DirectKeySignatureBuilder builder = new DirectKeySignatureBuilder(primaryKey, secretKeyRingProtector, prevDirectKeySig);
|
DirectKeySelfSignatureBuilder builder = new DirectKeySelfSignatureBuilder(primaryKey, secretKeyRingProtector, prevDirectKeySig);
|
||||||
System.out.println("FIXME"); // will cause checkstyle warning so I remember
|
builder.applyCallback(new SelfSignatureSubpackets.Callback() {
|
||||||
/*
|
|
||||||
builder.applyCallback(new CertificationSubpackets.Callback() {
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyHashedSubpackets(CertificationSubpackets hashedSubpackets) {
|
public void modifyHashedSubpackets(SelfSignatureSubpackets hashedSubpackets) {
|
||||||
if (expiration != null) {
|
if (expiration != null) {
|
||||||
hashedSubpackets.setKeyExpirationTime(keyCreationTime, expiration);
|
hashedSubpackets.setKeyExpirationTime(keyCreationTime, expiration);
|
||||||
} else {
|
} else {
|
||||||
|
@ -626,7 +623,6 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
|
|
||||||
return builder.build(publicKey);
|
return builder.build(publicKey);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package org.pgpainless.signature.builder;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
|
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||||
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
|
import org.bouncycastle.openpgp.PGPSignatureGenerator;
|
||||||
|
import org.pgpainless.algorithm.SignatureType;
|
||||||
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
|
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets;
|
||||||
|
|
||||||
|
public class DirectKeySelfSignatureBuilder extends AbstractSignatureBuilder<DirectKeySelfSignatureBuilder> {
|
||||||
|
|
||||||
|
public DirectKeySelfSignatureBuilder(PGPSecretKey certificationKey, SecretKeyRingProtector protector, PGPSignature archetypeSignature)
|
||||||
|
throws PGPException {
|
||||||
|
super(certificationKey, protector, archetypeSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DirectKeySelfSignatureBuilder(PGPSecretKey signingKey, SecretKeyRingProtector protector) throws PGPException {
|
||||||
|
super(SignatureType.DIRECT_KEY, signingKey, protector);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelfSignatureSubpackets getHashedSubpackets() {
|
||||||
|
return hashedSubpackets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelfSignatureSubpackets getUnhashedSubpackets() {
|
||||||
|
return unhashedSubpackets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyCallback(@Nullable SelfSignatureSubpackets.Callback callback) {
|
||||||
|
if (callback != null) {
|
||||||
|
callback.modifyHashedSubpackets(getHashedSubpackets());
|
||||||
|
callback.modifyUnhashedSubpackets(getUnhashedSubpackets());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PGPSignature build(PGPPublicKey key) throws PGPException {
|
||||||
|
PGPSignatureGenerator signatureGenerator = buildAndInitSignatureGenerator();
|
||||||
|
if (key.getKeyID() != publicSigningKey.getKeyID()) {
|
||||||
|
return signatureGenerator.generateCertification(publicSigningKey, key);
|
||||||
|
} else {
|
||||||
|
return signatureGenerator.generateCertification(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isValidSignatureType(SignatureType type) {
|
||||||
|
return type == SignatureType.DIRECT_KEY;
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,14 +15,14 @@ import org.pgpainless.algorithm.SignatureType;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
import org.pgpainless.signature.subpackets.CertificationSubpackets;
|
import org.pgpainless.signature.subpackets.CertificationSubpackets;
|
||||||
|
|
||||||
public class DirectKeySignatureBuilder extends AbstractSignatureBuilder<DirectKeySignatureBuilder> {
|
public class ThirdPartyDirectKeySignatureBuilder extends AbstractSignatureBuilder<ThirdPartyDirectKeySignatureBuilder> {
|
||||||
|
|
||||||
public DirectKeySignatureBuilder(PGPSecretKey certificationKey, SecretKeyRingProtector protector, PGPSignature archetypeSignature)
|
public ThirdPartyDirectKeySignatureBuilder(PGPSecretKey certificationKey, SecretKeyRingProtector protector, PGPSignature archetypeSignature)
|
||||||
throws PGPException {
|
throws PGPException {
|
||||||
super(certificationKey, protector, archetypeSignature);
|
super(certificationKey, protector, archetypeSignature);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DirectKeySignatureBuilder(PGPSecretKey signingKey, SecretKeyRingProtector protector) throws PGPException {
|
public ThirdPartyDirectKeySignatureBuilder(PGPSecretKey signingKey, SecretKeyRingProtector protector) throws PGPException {
|
||||||
super(SignatureType.DIRECT_KEY, signingKey, protector);
|
super(SignatureType.DIRECT_KEY, signingKey, protector);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package org.pgpainless.algorithm;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class TrustworthinessTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void fullyTrustedIntroducer() {
|
||||||
|
Trustworthiness it = Trustworthiness.fullyTrusted().introducer();
|
||||||
|
assertTrue(it.isFullyTrusted());
|
||||||
|
assertFalse(it.isNotTrusted());
|
||||||
|
|
||||||
|
assertTrue(it.isIntroducer());
|
||||||
|
assertFalse(it.canIntroduce(it));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void marginallyTrustedIntroducer() {
|
||||||
|
Trustworthiness it = Trustworthiness.marginallyTrusted().introducer();
|
||||||
|
assertFalse(it.isFullyTrusted());
|
||||||
|
assertTrue(it.isMarginallyTrusted());
|
||||||
|
assertFalse(it.isNotTrusted());
|
||||||
|
|
||||||
|
assertTrue(it.isIntroducer());
|
||||||
|
assertFalse(it.canIntroduce(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void nonTrustedIntroducer() {
|
||||||
|
Trustworthiness it = Trustworthiness.untrusted().introducer();
|
||||||
|
assertTrue(it.isNotTrusted());
|
||||||
|
assertFalse(it.isMarginallyTrusted());
|
||||||
|
assertFalse(it.isFullyTrusted());
|
||||||
|
|
||||||
|
assertTrue(it.isIntroducer());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void trustedMetaIntroducer() {
|
||||||
|
Trustworthiness it = Trustworthiness.fullyTrusted().metaIntroducer();
|
||||||
|
assertTrue(it.isFullyTrusted());
|
||||||
|
assertTrue(it.isIntroducer());
|
||||||
|
|
||||||
|
Trustworthiness that = Trustworthiness.fullyTrusted().introducer();
|
||||||
|
assertTrue(it.canIntroduce(that));
|
||||||
|
assertFalse(that.canIntroduce(it));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void invalidArguments() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> new Trustworthiness(300, 1));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> new Trustworthiness(60, 300));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> new Trustworthiness(-4, 1));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> new Trustworthiness(120, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void inBetweenValues() {
|
||||||
|
Trustworthiness it = new Trustworthiness(30, 1);
|
||||||
|
assertTrue(it.isMarginallyTrusted());
|
||||||
|
assertFalse(it.isFullyTrusted());
|
||||||
|
|
||||||
|
it = new Trustworthiness(140, 1);
|
||||||
|
assertTrue(it.isFullyTrusted());
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.bouncycastle.bcpg.sig.TrustSignature;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||||
|
@ -84,13 +85,19 @@ public class CertifyCertificateTest {
|
||||||
assertNotNull(signature);
|
assertNotNull(signature);
|
||||||
assertEquals(SignatureType.DIRECT_KEY, SignatureType.valueOf(signature.getSignatureType()));
|
assertEquals(SignatureType.DIRECT_KEY, SignatureType.valueOf(signature.getSignatureType()));
|
||||||
assertEquals(alice.getPublicKey().getKeyID(), signature.getKeyID());
|
assertEquals(alice.getPublicKey().getKeyID(), signature.getKeyID());
|
||||||
|
TrustSignature trustSignaturePacket = signature.getHashedSubPackets().getTrust();
|
||||||
|
assertNotNull(trustSignaturePacket);
|
||||||
|
Trustworthiness trustworthiness = new Trustworthiness(trustSignaturePacket.getTrustAmount(), trustSignaturePacket.getDepth());
|
||||||
|
assertTrue(trustworthiness.isFullyTrusted());
|
||||||
|
assertTrue(trustworthiness.isIntroducer());
|
||||||
|
assertFalse(trustworthiness.canIntroduce(1));
|
||||||
|
|
||||||
assertTrue(SignatureVerifier.verifyDirectKeySignature(
|
assertTrue(SignatureVerifier.verifyDirectKeySignature(
|
||||||
signature, alice.getPublicKey(), bob.getPublicKey(), PGPainless.getPolicy(), DateUtil.now()));
|
signature, alice.getPublicKey(), bob.getPublicKey(), PGPainless.getPolicy(), DateUtil.now()));
|
||||||
|
|
||||||
PGPPublicKeyRing bobCertified = result.getCertifiedCertificate();
|
PGPPublicKeyRing bobCertified = result.getCertifiedCertificate();
|
||||||
PGPPublicKey bobCertifiedKey = bobCertified.getPublicKey();
|
PGPPublicKey bobCertifiedKey = bobCertified.getPublicKey();
|
||||||
|
|
||||||
List<PGPSignature> sigsByAlice = CollectionUtils.iteratorToList(
|
List<PGPSignature> sigsByAlice = CollectionUtils.iteratorToList(
|
||||||
bobCertifiedKey.getSignaturesForKeyID(alice.getPublicKey().getKeyID()));
|
bobCertifiedKey.getSignaturesForKeyID(alice.getPublicKey().getKeyID()));
|
||||||
assertEquals(1, sigsByAlice.size());
|
assertEquals(1, sigsByAlice.size());
|
||||||
|
|
|
@ -29,19 +29,17 @@ import org.pgpainless.key.util.KeyRingUtils;
|
||||||
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets;
|
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets;
|
||||||
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
|
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
|
||||||
|
|
||||||
public class DirectKeySignatureBuilderTest {
|
public class ThirdPartyDirectKeySignatureBuilderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDirectKeySignatureBuilding() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, InterruptedException {
|
public void testDirectKeySignatureBuilding() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, InterruptedException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
||||||
.modernKeyRing("Alice");
|
.modernKeyRing("Alice");
|
||||||
|
|
||||||
DirectKeySignatureBuilder dsb = new DirectKeySignatureBuilder(
|
DirectKeySelfSignatureBuilder dsb = new DirectKeySelfSignatureBuilder(
|
||||||
secretKeys.getSecretKey(),
|
secretKeys.getSecretKey(),
|
||||||
SecretKeyRingProtector.unprotectedKeys());
|
SecretKeyRingProtector.unprotectedKeys());
|
||||||
|
|
||||||
System.out.println("FIXME"); // will cause checkstyle warning, so I remember
|
|
||||||
/*
|
|
||||||
dsb.applyCallback(new SelfSignatureSubpackets.Callback() {
|
dsb.applyCallback(new SelfSignatureSubpackets.Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void modifyHashedSubpackets(SelfSignatureSubpackets hashedSubpackets) {
|
public void modifyHashedSubpackets(SelfSignatureSubpackets hashedSubpackets) {
|
||||||
|
@ -52,7 +50,6 @@ public class DirectKeySignatureBuilderTest {
|
||||||
hashedSubpackets.setFeatures(Feature.MODIFICATION_DETECTION);
|
hashedSubpackets.setFeatures(Feature.MODIFICATION_DETECTION);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
|
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
|
|
Loading…
Reference in a new issue