mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-18 02:12:06 +01:00
WIP: Implement delegations
THERE ARE THINGS BROKEN NOW. DO NOT MERGE!
This commit is contained in:
parent
c1170773bc
commit
fa5ddfd112
7 changed files with 272 additions and 55 deletions
|
@ -165,7 +165,7 @@ public final class PGPainless {
|
||||||
return Policy.getInstance();
|
return Policy.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CertifyCertificate certifyCertificate() {
|
public static CertifyCertificate certify() {
|
||||||
return new CertifyCertificate();
|
return new CertifyCertificate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package org.pgpainless.algorithm;
|
||||||
|
|
||||||
|
public class Trustworthiness {
|
||||||
|
|
||||||
|
private final int amount;
|
||||||
|
private final int depth;
|
||||||
|
|
||||||
|
public static final int THRESHOLD_FULLY_CONVINCED = 120;
|
||||||
|
public static final int THRESHOLD_MARGINALLY_CONVINCED = 60;
|
||||||
|
public static final int THRESHOLD_NOT_TRUSTED = 0;
|
||||||
|
|
||||||
|
public Trustworthiness(int amount, int depth) {
|
||||||
|
this.amount = capAmount(amount);
|
||||||
|
this.depth = capDepth(depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAmount() {
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDepth() {
|
||||||
|
return depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This means that we are fully convinced of the trustworthiness of the key.
|
||||||
|
*
|
||||||
|
* @return builder
|
||||||
|
*/
|
||||||
|
public static Builder fullyTrusted() {
|
||||||
|
return new Builder(THRESHOLD_FULLY_CONVINCED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This means that we are marginally (partially) convinced of the trustworthiness of the key.
|
||||||
|
*
|
||||||
|
* @return builder
|
||||||
|
*/
|
||||||
|
public static Builder marginallyTrusted() {
|
||||||
|
return new Builder(THRESHOLD_MARGINALLY_CONVINCED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This means that we do not trust the key.
|
||||||
|
* Can be used to overwrite previous trust.
|
||||||
|
*
|
||||||
|
* @return builder
|
||||||
|
*/
|
||||||
|
public static Builder untrusted() {
|
||||||
|
return new Builder(THRESHOLD_NOT_TRUSTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Builder {
|
||||||
|
|
||||||
|
private final int amount;
|
||||||
|
|
||||||
|
private Builder(int amount) {
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The key is a trusted introducer (depth 1).
|
||||||
|
* Certifications made by this key are considered trustworthy.
|
||||||
|
*
|
||||||
|
* @return trust
|
||||||
|
*/
|
||||||
|
public Trustworthiness introducer() {
|
||||||
|
return new Trustworthiness(amount, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The key is a meta introducer (depth 2).
|
||||||
|
* This key can introduce trusted introducers of depth 1.
|
||||||
|
*
|
||||||
|
* @return trust
|
||||||
|
*/
|
||||||
|
public Trustworthiness metaIntroducer() {
|
||||||
|
return new Trustworthiness(amount, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The key is a level <pre>n</pre> meta introducer.
|
||||||
|
* This key can introduce meta introducers of depth <pre>n - 1</pre>.
|
||||||
|
*
|
||||||
|
* @param n depth
|
||||||
|
* @return trust
|
||||||
|
*/
|
||||||
|
public Trustworthiness levelNIntroducer(int n) {
|
||||||
|
return new Trustworthiness(amount, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int capAmount(int amount) {
|
||||||
|
if (amount < 0 || amount > 255) {
|
||||||
|
throw new IllegalArgumentException("Trust amount MUST be a value between 0 and 255");
|
||||||
|
}
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int capDepth(int depth) {
|
||||||
|
if (depth < 0 || depth > 255) {
|
||||||
|
throw new IllegalArgumentException("Trust depth MUST be a value between 0 and 255");
|
||||||
|
}
|
||||||
|
return depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -13,40 +13,151 @@ import org.bouncycastle.openpgp.PGPSignature;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.algorithm.CertificationType;
|
import org.pgpainless.algorithm.CertificationType;
|
||||||
import org.pgpainless.algorithm.KeyFlag;
|
import org.pgpainless.algorithm.KeyFlag;
|
||||||
|
import org.pgpainless.algorithm.Trustworthiness;
|
||||||
import org.pgpainless.exception.KeyException;
|
import org.pgpainless.exception.KeyException;
|
||||||
import org.pgpainless.key.OpenPgpFingerprint;
|
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.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;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
public class CertifyCertificate {
|
public class CertifyCertificate {
|
||||||
|
|
||||||
CertifyUserId certifyUserId(PGPPublicKeyRing certificate, String userId) {
|
CertificationOnUserId userIdOnCertificate(@Nonnull String userId, @Nonnull PGPPublicKeyRing certificate) {
|
||||||
return new CertifyUserId(certificate, userId);
|
return new CertificationOnUserId(userId, certificate, CertificationType.GENERIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CertifyUserId {
|
CertificationOnUserId userIdOnCertificate(@Nonnull String userid, @Nonnull PGPPublicKeyRing certificate, @Nonnull CertificationType certificationType) {
|
||||||
|
return new CertificationOnUserId(userid, certificate, certificationType);
|
||||||
|
}
|
||||||
|
|
||||||
|
DelegationOnCertificate certificate(@Nonnull PGPPublicKeyRing certificate) {
|
||||||
|
return certificate(certificate, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
DelegationOnCertificate certificate(@Nonnull PGPPublicKeyRing certificate, @Nullable Trustworthiness trustworthiness) {
|
||||||
|
return new DelegationOnCertificate(certificate, trustworthiness);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CertificationOnUserId {
|
||||||
|
|
||||||
private final PGPPublicKeyRing certificate;
|
private final PGPPublicKeyRing certificate;
|
||||||
private final String userId;
|
private final String userId;
|
||||||
private final CertificationType certificationType;
|
private final CertificationType certificationType;
|
||||||
|
|
||||||
CertifyUserId(PGPPublicKeyRing certificate, String userId) {
|
CertificationOnUserId(@Nonnull String userId, @Nonnull PGPPublicKeyRing certificate, @Nonnull CertificationType certificationType) {
|
||||||
this(certificate, userId, CertificationType.GENERIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
CertifyUserId(PGPPublicKeyRing certificate, String userId, CertificationType certificationType) {
|
|
||||||
this.certificate = certificate;
|
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
|
this.certificate = certificate;
|
||||||
this.certificationType = certificationType;
|
this.certificationType = certificationType;
|
||||||
}
|
}
|
||||||
|
|
||||||
CertifyUserIdWithSubpackets withKey(PGPSecretKeyRing certificationKey, SecretKeyRingProtector protector) throws PGPException {
|
CertificationOnUserIdWithSubpackets withKey(@Nonnull PGPSecretKeyRing certificationKey, @Nonnull SecretKeyRingProtector protector) throws PGPException {
|
||||||
|
PGPSecretKey secretKey = getCertificationSecretKey(certificationKey);
|
||||||
|
|
||||||
|
ThirdPartyCertificationSignatureBuilder sigBuilder = new ThirdPartyCertificationSignatureBuilder(
|
||||||
|
certificationType.asSignatureType(), secretKey, protector);
|
||||||
|
|
||||||
|
return new CertificationOnUserIdWithSubpackets(certificate, userId, sigBuilder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CertificationOnUserIdWithSubpackets {
|
||||||
|
|
||||||
|
private final PGPPublicKeyRing certificate;
|
||||||
|
private final String userId;
|
||||||
|
private final ThirdPartyCertificationSignatureBuilder sigBuilder;
|
||||||
|
|
||||||
|
CertificationOnUserIdWithSubpackets(@Nonnull PGPPublicKeyRing certificate, @Nonnull String userId, @Nonnull ThirdPartyCertificationSignatureBuilder sigBuilder) {
|
||||||
|
this.certificate = certificate;
|
||||||
|
this.userId = userId;
|
||||||
|
this.sigBuilder = sigBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CertificationResult withSubpackets(@Nonnull CertificationSubpackets.Callback subpacketCallback) throws PGPException {
|
||||||
|
sigBuilder.applyCallback(subpacketCallback);
|
||||||
|
return build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CertificationResult build() throws PGPException {
|
||||||
|
PGPSignature signature = sigBuilder.build(certificate, userId);
|
||||||
|
PGPPublicKeyRing certifiedCertificate = KeyRingUtils.injectCertification(certificate, userId, signature);
|
||||||
|
return new CertificationResult(certifiedCertificate, signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DelegationOnCertificate {
|
||||||
|
|
||||||
|
private final PGPPublicKeyRing certificate;
|
||||||
|
private final Trustworthiness trustworthiness;
|
||||||
|
|
||||||
|
DelegationOnCertificate(@Nonnull PGPPublicKeyRing certificate, @Nullable Trustworthiness trustworthiness) {
|
||||||
|
this.certificate = certificate;
|
||||||
|
this.trustworthiness = trustworthiness;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DelegationOnCertificateWithSubpackets withKey(@Nonnull PGPSecretKeyRing certificationKey, @Nonnull SecretKeyRingProtector protector) throws PGPException {
|
||||||
|
PGPSecretKey secretKey = getCertificationSecretKey(certificationKey);
|
||||||
|
|
||||||
|
DirectKeySignatureBuilder sigBuilder = new DirectKeySignatureBuilder(secretKey, protector);
|
||||||
|
if (trustworthiness != null) {
|
||||||
|
sigBuilder.getHashedSubpackets().setTrust(true, trustworthiness.getDepth(), trustworthiness.getAmount());
|
||||||
|
}
|
||||||
|
return new DelegationOnCertificateWithSubpackets(certificate, sigBuilder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DelegationOnCertificateWithSubpackets {
|
||||||
|
|
||||||
|
private final PGPPublicKeyRing certificate;
|
||||||
|
private final DirectKeySignatureBuilder sigBuilder;
|
||||||
|
|
||||||
|
public DelegationOnCertificateWithSubpackets(@Nonnull PGPPublicKeyRing certificate, @Nonnull DirectKeySignatureBuilder sigBuilder) {
|
||||||
|
this.certificate = certificate;
|
||||||
|
this.sigBuilder = sigBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CertificationResult withSubpackets(@Nonnull CertificationSubpackets.Callback subpacketsCallback) throws PGPException {
|
||||||
|
sigBuilder.applyCallback(subpacketsCallback);
|
||||||
|
return build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CertificationResult build() throws PGPException {
|
||||||
|
PGPPublicKey delegatedKey = certificate.getPublicKey();
|
||||||
|
PGPSignature delegation = sigBuilder.build(delegatedKey);
|
||||||
|
PGPPublicKeyRing delegatedCertificate = KeyRingUtils.injectCertification(certificate, delegatedKey, delegation);
|
||||||
|
return new CertificationResult(delegatedCertificate, delegation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CertificationResult {
|
||||||
|
|
||||||
|
private final PGPPublicKeyRing certificate;
|
||||||
|
private final PGPSignature certification;
|
||||||
|
|
||||||
|
CertificationResult(@Nonnull PGPPublicKeyRing certificate, @Nonnull PGPSignature certification) {
|
||||||
|
this.certificate = certificate;
|
||||||
|
this.certification = certification;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public PGPSignature getCertification() {
|
||||||
|
return certification;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public PGPPublicKeyRing getCertifiedCertificate() {
|
||||||
|
return certificate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PGPSecretKey getCertificationSecretKey(PGPSecretKeyRing certificationKey) {
|
||||||
Date now = DateUtil.now();
|
Date now = DateUtil.now();
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(certificationKey, now);
|
KeyRingInfo info = PGPainless.inspectKeyRing(certificationKey, now);
|
||||||
|
|
||||||
|
@ -66,58 +177,7 @@ public class CertifyCertificate {
|
||||||
if (secretKey == null) {
|
if (secretKey == null) {
|
||||||
throw new KeyException.MissingSecretKeyException(fingerprint, certificationPubKey.getKeyID());
|
throw new KeyException.MissingSecretKeyException(fingerprint, certificationPubKey.getKeyID());
|
||||||
}
|
}
|
||||||
|
return secretKey;
|
||||||
ThirdPartyCertificationSignatureBuilder sigBuilder = new ThirdPartyCertificationSignatureBuilder(
|
|
||||||
certificationType.asSignatureType(), secretKey, protector);
|
|
||||||
|
|
||||||
return new CertifyUserIdWithSubpackets(certificate, userId, sigBuilder);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CertifyUserIdWithSubpackets {
|
|
||||||
|
|
||||||
private final PGPPublicKeyRing certificate;
|
|
||||||
private final String userId;
|
|
||||||
private final ThirdPartyCertificationSignatureBuilder sigBuilder;
|
|
||||||
|
|
||||||
CertifyUserIdWithSubpackets(PGPPublicKeyRing certificate, String userId, ThirdPartyCertificationSignatureBuilder sigBuilder) {
|
|
||||||
this.certificate = certificate;
|
|
||||||
this.userId = userId;
|
|
||||||
this.sigBuilder = sigBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CertifyUserIdResult withSubpackets(CertificationSubpackets.Callback subpacketCallback) throws PGPException {
|
|
||||||
sigBuilder.applyCallback(subpacketCallback);
|
|
||||||
return build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CertifyUserIdResult build() throws PGPException {
|
|
||||||
PGPSignature signature = sigBuilder.build(certificate, userId);
|
|
||||||
|
|
||||||
return new CertifyUserIdResult(certificate, userId, signature);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class CertifyUserIdResult {
|
|
||||||
|
|
||||||
private final PGPPublicKeyRing certificate;
|
|
||||||
private final String userId;
|
|
||||||
private final PGPSignature certification;
|
|
||||||
|
|
||||||
CertifyUserIdResult(PGPPublicKeyRing certificate, String userId, PGPSignature certification) {
|
|
||||||
this.certificate = certificate;
|
|
||||||
this.userId = userId;
|
|
||||||
this.certification = certification;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PGPSignature getCertification() {
|
|
||||||
return certification;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PGPPublicKeyRing getCertifiedCertificate() {
|
|
||||||
// inject the signature
|
|
||||||
PGPPublicKeyRing certified = KeyRingUtils.injectCertification(certificate, userId, certification);
|
|
||||||
return certified;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ import org.pgpainless.key.util.RevocationAttributes;
|
||||||
import org.pgpainless.signature.builder.DirectKeySignatureBuilder;
|
import org.pgpainless.signature.builder.DirectKeySignatureBuilder;
|
||||||
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,9 +614,11 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
|
||||||
final Date keyCreationTime = publicKey.getCreationTime();
|
final Date keyCreationTime = publicKey.getCreationTime();
|
||||||
|
|
||||||
DirectKeySignatureBuilder builder = new DirectKeySignatureBuilder(primaryKey, secretKeyRingProtector, prevDirectKeySig);
|
DirectKeySignatureBuilder builder = new DirectKeySignatureBuilder(primaryKey, secretKeyRingProtector, prevDirectKeySig);
|
||||||
builder.applyCallback(new SelfSignatureSubpackets.Callback() {
|
System.out.println("FIXME"); // will cause checkstyle warning so I remember
|
||||||
|
/*
|
||||||
|
builder.applyCallback(new CertificationSubpackets.Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void modifyHashedSubpackets(SelfSignatureSubpackets hashedSubpackets) {
|
public void modifyHashedSubpackets(CertificationSubpackets hashedSubpackets) {
|
||||||
if (expiration != null) {
|
if (expiration != null) {
|
||||||
hashedSubpackets.setKeyExpirationTime(keyCreationTime, expiration);
|
hashedSubpackets.setKeyExpirationTime(keyCreationTime, expiration);
|
||||||
} else {
|
} else {
|
||||||
|
@ -623,6 +626,7 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
return builder.build(publicKey);
|
return builder.build(publicKey);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,10 @@ import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
|
import org.bouncycastle.openpgp.PGPSignatureGenerator;
|
||||||
import org.pgpainless.algorithm.SignatureType;
|
import org.pgpainless.algorithm.SignatureType;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets;
|
import org.pgpainless.signature.subpackets.CertificationSubpackets;
|
||||||
|
|
||||||
public class DirectKeySignatureBuilder extends AbstractSignatureBuilder<DirectKeySignatureBuilder> {
|
public class DirectKeySignatureBuilder extends AbstractSignatureBuilder<DirectKeySignatureBuilder> {
|
||||||
|
|
||||||
|
@ -25,15 +26,15 @@ public class DirectKeySignatureBuilder extends AbstractSignatureBuilder<DirectKe
|
||||||
super(SignatureType.DIRECT_KEY, signingKey, protector);
|
super(SignatureType.DIRECT_KEY, signingKey, protector);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SelfSignatureSubpackets getHashedSubpackets() {
|
public CertificationSubpackets getHashedSubpackets() {
|
||||||
return hashedSubpackets;
|
return hashedSubpackets;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SelfSignatureSubpackets getUnhashedSubpackets() {
|
public CertificationSubpackets getUnhashedSubpackets() {
|
||||||
return unhashedSubpackets;
|
return unhashedSubpackets;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyCallback(@Nullable SelfSignatureSubpackets.Callback callback) {
|
public void applyCallback(@Nullable CertificationSubpackets.Callback callback) {
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
callback.modifyHashedSubpackets(getHashedSubpackets());
|
callback.modifyHashedSubpackets(getHashedSubpackets());
|
||||||
callback.modifyUnhashedSubpackets(getUnhashedSubpackets());
|
callback.modifyUnhashedSubpackets(getUnhashedSubpackets());
|
||||||
|
@ -41,8 +42,12 @@ public class DirectKeySignatureBuilder extends AbstractSignatureBuilder<DirectKe
|
||||||
}
|
}
|
||||||
|
|
||||||
public PGPSignature build(PGPPublicKey key) throws PGPException {
|
public PGPSignature build(PGPPublicKey key) throws PGPException {
|
||||||
return buildAndInitSignatureGenerator()
|
PGPSignatureGenerator signatureGenerator = buildAndInitSignatureGenerator();
|
||||||
.generateCertification(key);
|
if (key.getKeyID() != publicSigningKey.getKeyID()) {
|
||||||
|
return signatureGenerator.generateCertification(publicSigningKey, key);
|
||||||
|
} else {
|
||||||
|
return signatureGenerator.generateCertification(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.bouncycastle.util.Arrays;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.algorithm.SignatureType;
|
import org.pgpainless.algorithm.SignatureType;
|
||||||
|
import org.pgpainless.algorithm.Trustworthiness;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
import org.pgpainless.signature.consumer.SignatureVerifier;
|
import org.pgpainless.signature.consumer.SignatureVerifier;
|
||||||
import org.pgpainless.util.CollectionUtils;
|
import org.pgpainless.util.CollectionUtils;
|
||||||
|
@ -31,7 +32,7 @@ import org.pgpainless.util.DateUtil;
|
||||||
public class CertifyCertificateTest {
|
public class CertifyCertificateTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccessfulCertificationOfUserId() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException {
|
public void testUserIdCertification() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException {
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
||||||
PGPSecretKeyRing alice = PGPainless.generateKeyRing().modernKeyRing("Alice <alice@pgpainless.org>", null);
|
PGPSecretKeyRing alice = PGPainless.generateKeyRing().modernKeyRing("Alice <alice@pgpainless.org>", null);
|
||||||
String bobUserId = "Bob <bob@pgpainless.org>";
|
String bobUserId = "Bob <bob@pgpainless.org>";
|
||||||
|
@ -39,8 +40,8 @@ public class CertifyCertificateTest {
|
||||||
|
|
||||||
PGPPublicKeyRing bobCertificate = PGPainless.extractCertificate(bob);
|
PGPPublicKeyRing bobCertificate = PGPainless.extractCertificate(bob);
|
||||||
|
|
||||||
CertifyCertificate.CertifyUserIdResult result = PGPainless.certifyCertificate()
|
CertifyCertificate.CertificationResult result = PGPainless.certify()
|
||||||
.certifyUserId(bobCertificate, bobUserId)
|
.userIdOnCertificate(bobUserId, bobCertificate)
|
||||||
.withKey(alice, protector)
|
.withKey(alice, protector)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -64,4 +65,37 @@ public class CertifyCertificateTest {
|
||||||
|
|
||||||
assertFalse(Arrays.areEqual(bobCertificate.getEncoded(), bobCertified.getEncoded()));
|
assertFalse(Arrays.areEqual(bobCertificate.getEncoded(), bobCertified.getEncoded()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testKeyDelegation() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException {
|
||||||
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
||||||
|
PGPSecretKeyRing alice = PGPainless.generateKeyRing().modernKeyRing("Alice <alice@pgpainless.org>", null);
|
||||||
|
PGPSecretKeyRing bob = PGPainless.generateKeyRing().modernKeyRing("Bob <bob@pgpainless.org>", null);
|
||||||
|
|
||||||
|
PGPPublicKeyRing bobCertificate = PGPainless.extractCertificate(bob);
|
||||||
|
|
||||||
|
CertifyCertificate.CertificationResult result = PGPainless.certify()
|
||||||
|
.certificate(bobCertificate, Trustworthiness.fullyTrusted().introducer())
|
||||||
|
.withKey(alice, protector)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
PGPSignature signature = result.getCertification();
|
||||||
|
assertNotNull(signature);
|
||||||
|
assertEquals(SignatureType.DIRECT_KEY, SignatureType.valueOf(signature.getSignatureType()));
|
||||||
|
assertEquals(alice.getPublicKey().getKeyID(), signature.getKeyID());
|
||||||
|
|
||||||
|
assertTrue(SignatureVerifier.verifyDirectKeySignature(
|
||||||
|
signature, alice.getPublicKey(), bob.getPublicKey(), PGPainless.getPolicy(), DateUtil.now()));
|
||||||
|
|
||||||
|
PGPPublicKeyRing bobCertified = result.getCertifiedCertificate();
|
||||||
|
PGPPublicKey bobCertifiedKey = bobCertified.getPublicKey();
|
||||||
|
|
||||||
|
List<PGPSignature> sigsByAlice = CollectionUtils.iteratorToList(
|
||||||
|
bobCertifiedKey.getSignaturesForKeyID(alice.getPublicKey().getKeyID()));
|
||||||
|
assertEquals(1, sigsByAlice.size());
|
||||||
|
assertEquals(signature, sigsByAlice.get(0));
|
||||||
|
|
||||||
|
assertFalse(Arrays.areEqual(bobCertificate.getEncoded(), bobCertified.getEncoded()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,8 @@ public class DirectKeySignatureBuilderTest {
|
||||||
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) {
|
||||||
|
@ -50,6 +52,7 @@ 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