mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-24 11:57:59 +01:00
Introduce CertificationFactory.
This is done in an attempt to minimize the number of BC/PGPainless dependencies in wot-dijkstra
This commit is contained in:
parent
2de7c0aa36
commit
c213760e6c
7 changed files with 155 additions and 67 deletions
|
@ -531,6 +531,11 @@ public final class SignatureSubpacketsUtil {
|
|||
return hashed(signature, SignatureSubpacket.exportableCertification);
|
||||
}
|
||||
|
||||
public static boolean isExportable(PGPSignature signature) {
|
||||
Exportable exportable = getExportableCertification(signature);
|
||||
return exportable == null || exportable.isExportable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the trust signature packet from the signatures hashed area.
|
||||
*
|
||||
|
@ -541,6 +546,22 @@ public final class SignatureSubpacketsUtil {
|
|||
return hashed(signature, SignatureSubpacket.trustSignature);
|
||||
}
|
||||
|
||||
public static int getTrustDepthOr(PGPSignature signature, int defaultDepth) {
|
||||
TrustSignature packet = getTrustSignature(signature);
|
||||
if (packet != null) {
|
||||
return packet.getDepth();
|
||||
}
|
||||
return defaultDepth;
|
||||
}
|
||||
|
||||
public static int getTrustAmountOr(PGPSignature signature, int defaultAmount) {
|
||||
TrustSignature packet = getTrustSignature(signature);
|
||||
if (packet != null) {
|
||||
return packet.getTrustAmount();
|
||||
}
|
||||
return defaultAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all regular expression subpackets from the hashed area of the given signature.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.wot;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bouncycastle.bcpg.sig.RegularExpression;
|
||||
import org.bouncycastle.bcpg.sig.TrustSignature;
|
||||
import org.bouncycastle.openpgp.PGPSignature;
|
||||
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
|
||||
import org.pgpainless.wot.dijkstra.sq.CertSynopsis;
|
||||
import org.pgpainless.wot.dijkstra.sq.Certification;
|
||||
import org.pgpainless.wot.dijkstra.sq.Depth;
|
||||
import org.pgpainless.wot.dijkstra.sq.Optional;
|
||||
import org.pgpainless.wot.dijkstra.sq.RegexSet;
|
||||
|
||||
/**
|
||||
* Factory class for creating {@link Certification} objects from {@link PGPSignature PGPSignatures}.
|
||||
* The purpose of this class is to minimize the number of PGPainless / Bouncycastle class dependencies in wot-dijkstra.
|
||||
*/
|
||||
public class CertificationFactory {
|
||||
|
||||
/**
|
||||
* Create a {@link Certification} object from a delegation signature.
|
||||
*
|
||||
* @param issuer signature issuer certificate
|
||||
* @param target signature target certificate
|
||||
* @param signature signature
|
||||
* @return certification
|
||||
*/
|
||||
public static Certification fromDelegation(CertSynopsis issuer,
|
||||
CertSynopsis target,
|
||||
PGPSignature signature) {
|
||||
return fromSignature(issuer, Optional.empty(), target, signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link Certification} object from a certification signature.
|
||||
*
|
||||
* @param issuer signature issuer certificate
|
||||
* @param targetUserId signature target user ID
|
||||
* @param target signature target certificate
|
||||
* @param signature signature
|
||||
* @return certification
|
||||
*/
|
||||
public static Certification fromCertification(CertSynopsis issuer,
|
||||
String targetUserId,
|
||||
CertSynopsis target,
|
||||
PGPSignature signature) {
|
||||
return fromSignature(issuer, Optional.just(targetUserId), target, signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link Certification} object from a signature.
|
||||
*
|
||||
* @param issuer signature issuer certificate
|
||||
* @param targetUserId optional signature target user ID
|
||||
* @param target signature target certificate
|
||||
* @param signature signature
|
||||
* @return certification
|
||||
*/
|
||||
public static Certification fromSignature(CertSynopsis issuer,
|
||||
Optional<String> targetUserId,
|
||||
CertSynopsis target,
|
||||
PGPSignature signature) {
|
||||
return new Certification(
|
||||
issuer,
|
||||
target,
|
||||
targetUserId,
|
||||
SignatureSubpacketsUtil.getSignatureCreationTime(signature).getTime(),
|
||||
Optional.maybe(SignatureSubpacketsUtil.getSignatureExpirationTimeAsDate(signature)),
|
||||
SignatureSubpacketsUtil.isExportable(signature),
|
||||
getTrustAmountFrom(signature),
|
||||
getTrustDepthFrom(signature),
|
||||
regexSetFrom(signature));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the trust amount from the signature.
|
||||
* If the signature has no {@link TrustSignature} subpacket, return a default value of 120.
|
||||
*
|
||||
* @param signature signature
|
||||
* @return trust amount
|
||||
*/
|
||||
private static int getTrustAmountFrom(PGPSignature signature) {
|
||||
TrustSignature packet = SignatureSubpacketsUtil.getTrustSignature(signature);
|
||||
if (packet != null) {
|
||||
return packet.getTrustAmount();
|
||||
}
|
||||
return 120; // default value
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the trust depth from the signature.
|
||||
* If the signature has no {@link TrustSignature} subpacket, return a default value of 0.
|
||||
*
|
||||
* @param signature signature
|
||||
* @return trust depth
|
||||
*/
|
||||
private static Depth getTrustDepthFrom(PGPSignature signature) {
|
||||
TrustSignature packet = SignatureSubpacketsUtil.getTrustSignature(signature);
|
||||
if (packet != null) {
|
||||
return Depth.auto(packet.getDepth());
|
||||
}
|
||||
return Depth.limited(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a {@link RegexSet} from the signature.
|
||||
* If the signature has no {@link RegularExpression} subpacket, the result will equate to a wildcard.
|
||||
*
|
||||
* @param signature signature
|
||||
* @return regex set
|
||||
*/
|
||||
private static RegexSet regexSetFrom(PGPSignature signature) {
|
||||
List<RegularExpression> regexList = SignatureSubpacketsUtil.getRegularExpressions(signature);
|
||||
List<String> stringList = new ArrayList<>();
|
||||
for (RegularExpression regex : regexList) {
|
||||
stringList.add(regex.getRegex());
|
||||
}
|
||||
return RegexSet.fromExpressionList(stringList);
|
||||
}
|
||||
}
|
|
@ -246,7 +246,7 @@ public class WebOfTrust implements CertificateAuthority {
|
|||
boolean valid = SignatureVerifier.verifyDirectKeySignature(delegation, issuerSigningKey,
|
||||
targetPrimaryKey, policy, referenceTime.getTimestamp());
|
||||
if (valid) {
|
||||
indexEdge(new Certification(issuer, Optional.empty(), target, delegation));
|
||||
indexEdge(CertificationFactory.fromDelegation(issuer, target, delegation));
|
||||
}
|
||||
} catch (SignatureValidationException e) {
|
||||
LOGGER.warn("Cannot verify signature by " + issuerFingerprint + " on cert of " + OpenPgpFingerprint.of(targetPrimaryKey), e);
|
||||
|
@ -273,7 +273,7 @@ public class WebOfTrust implements CertificateAuthority {
|
|||
boolean valid = SignatureVerifier.verifySignatureOverUserId(userId, certification,
|
||||
issuerSigningKey, targetPrimaryKey, policy, referenceTime.getTimestamp());
|
||||
if (valid) {
|
||||
indexEdge(new Certification(issuer, Optional.just(userId), target, certification));
|
||||
indexEdge(CertificationFactory.fromCertification(issuer, userId, target, certification));
|
||||
}
|
||||
} catch (SignatureValidationException e) {
|
||||
LOGGER.warn("Cannot verify signature for '" + userId + "' by " + issuerFingerprint + " on cert of " + target.getFingerprint(), e);
|
||||
|
|
|
@ -34,6 +34,7 @@ dependencies {
|
|||
// @Nullable, @Nonnull annotations
|
||||
implementation "com.google.code.findbugs:jsr305:3.0.2"
|
||||
|
||||
// OpenPgpFingerprint, RevocationState
|
||||
implementation(project(":pgpainless-core"))
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,6 @@
|
|||
package org.pgpainless.wot.dijkstra.sq;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.bouncycastle.bcpg.sig.Exportable;
|
||||
import org.bouncycastle.bcpg.sig.RegularExpression;
|
||||
import org.bouncycastle.bcpg.sig.TrustSignature;
|
||||
import org.bouncycastle.openpgp.PGPSignature;
|
||||
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
|
||||
|
||||
public class Certification {
|
||||
|
||||
|
@ -63,29 +56,6 @@ public class Certification {
|
|||
this.regex = RegexSet.wildcard();
|
||||
}
|
||||
|
||||
public Certification(CertSynopsis issuer,
|
||||
Optional<String> targetUserId,
|
||||
CertSynopsis target,
|
||||
PGPSignature signature) {
|
||||
this.issuer = issuer;
|
||||
this.target = target;
|
||||
this.userId = targetUserId;
|
||||
this.creationTime = SignatureSubpacketsUtil.getSignatureCreationTime(signature).getTime();
|
||||
this.expirationTime = Optional.maybe(SignatureSubpacketsUtil.getSignatureExpirationTimeAsDate(signature));
|
||||
Exportable exportablePacket = SignatureSubpacketsUtil.getExportableCertification(signature);
|
||||
this.exportable = exportablePacket == null || exportablePacket.isExportable();
|
||||
TrustSignature trustSignaturePacket = SignatureSubpacketsUtil.getTrustSignature(signature);
|
||||
if (trustSignaturePacket == null) {
|
||||
this.trustDepth = Depth.limited(0);
|
||||
this.trustAmount = 120;
|
||||
} else {
|
||||
this.trustDepth = Depth.auto(trustSignaturePacket.getDepth());
|
||||
this.trustAmount = trustSignaturePacket.getTrustAmount();
|
||||
}
|
||||
List<RegularExpression> regularExpressionList = SignatureSubpacketsUtil.getRegularExpressions(signature);
|
||||
this.regex = RegexSet.fromList(regularExpressionList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the issuer of the certification.
|
||||
*
|
||||
|
|
|
@ -9,8 +9,6 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bouncycastle.openpgp.PGPSignature;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
|
@ -42,29 +40,6 @@ public final class CertificationSet {
|
|||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link CertificationSet} from a single certification.
|
||||
*
|
||||
* @param issuer issuer
|
||||
* @param target target
|
||||
* @param userId user-id
|
||||
* @param certification certification
|
||||
* @return singleton set
|
||||
*/
|
||||
public static CertificationSet fromCertification(
|
||||
CertSynopsis issuer,
|
||||
CertSynopsis target,
|
||||
Optional<String> userId,
|
||||
PGPSignature certification) {
|
||||
|
||||
Map<Optional<String>, List<Certification>> certificationMap = new HashMap<>();
|
||||
List<Certification> certificationList = new ArrayList<>();
|
||||
certificationList.add(new Certification(issuer, userId, target, certification));
|
||||
certificationMap.put(userId, certificationList);
|
||||
|
||||
return new CertificationSet(issuer, target, certificationMap);
|
||||
}
|
||||
|
||||
private CertificationSet(CertSynopsis issuer,
|
||||
CertSynopsis target,
|
||||
Map<Optional<String>, List<Certification>> certifications) {
|
||||
|
|
|
@ -12,8 +12,6 @@ import java.util.regex.Matcher;
|
|||
import java.util.regex.Pattern;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.bouncycastle.bcpg.sig.RegularExpression;
|
||||
|
||||
public final class RegexSet {
|
||||
|
||||
private final Set<String> regexStrings;
|
||||
|
@ -22,20 +20,17 @@ public final class RegexSet {
|
|||
this.regexStrings = regexStrings;
|
||||
}
|
||||
|
||||
public static RegexSet fromList(@Nonnull List<RegularExpression> regexList) {
|
||||
Set<String> regexStringSet = new HashSet<>();
|
||||
for (RegularExpression regex : regexList) {
|
||||
regexStringSet.add(regex.getRegex());
|
||||
}
|
||||
public static RegexSet fromExpressionList(@Nonnull List<String> regexList) {
|
||||
Set<String> regexStringSet = new HashSet<>(regexList);
|
||||
return new RegexSet(regexStringSet);
|
||||
}
|
||||
|
||||
public static RegexSet fromRegex(@Nonnull RegularExpression regex) {
|
||||
return fromList(Collections.singletonList(regex));
|
||||
public static RegexSet fromExpression(@Nonnull String regex) {
|
||||
return fromExpressionList(Collections.singletonList(regex));
|
||||
}
|
||||
|
||||
public static RegexSet wildcard() {
|
||||
return fromList(Collections.emptyList());
|
||||
return fromExpressionList(Collections.emptyList());
|
||||
}
|
||||
|
||||
public boolean matches(String string) {
|
||||
|
|
Loading…
Reference in a new issue