1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2025-12-10 06:11:08 +01:00

Do some first prototype algorithm negotiation

This commit is contained in:
Paul Schaub 2021-05-24 18:51:37 +02:00
parent 909f0e7be3
commit 4e63313c91
4 changed files with 239 additions and 2 deletions

View file

@ -17,6 +17,12 @@ package org.pgpainless.encryption_signing;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
import org.bouncycastle.openpgp.PGPException;
@ -31,6 +37,8 @@ import org.pgpainless.algorithm.HashAlgorithm;
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
import org.pgpainless.decryption_verification.OpenPgpMetadata;
import org.pgpainless.exception.KeyValidationException;
import org.pgpainless.key.SubkeyIdentifier;
import org.pgpainless.key.info.KeyView;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.policy.Policy;
import org.pgpainless.util.Passphrase;
@ -267,7 +275,33 @@ public class EncryptionBuilder implements EncryptionBuilderInterface {
return encryptionAlgorithmOverride;
}
// TODO: Negotiation
Map<SymmetricKeyAlgorithm, Integer> supportWeight = new LinkedHashMap<>();
for (SubkeyIdentifier key : encryptionOptions.getKeyViews().keySet()) {
KeyView keyView = encryptionOptions.getKeyViews().get(key);
for (SymmetricKeyAlgorithm preferred : keyView.getPreferredSymmetricKeyAlgorithms()) {
if (supportWeight.containsKey(preferred)) {
supportWeight.put(preferred, supportWeight.get(preferred) + 1);
} else {
supportWeight.put(preferred, 1);
}
}
}
List<SymmetricKeyAlgorithm> scoreboard = new ArrayList<>(supportWeight.keySet());
// Sort scoreboard by descending popularity
Collections.sort(scoreboard, new Comparator<SymmetricKeyAlgorithm>() {
@Override
public int compare(SymmetricKeyAlgorithm t0, SymmetricKeyAlgorithm t1) {
return -supportWeight.get(t0).compareTo(supportWeight.get(t1));
}
});
for (SymmetricKeyAlgorithm mostWanted : scoreboard) {
if (PGPainless.getPolicy().getSymmetricKeyEncryptionAlgorithmPolicy().isAcceptable(mostWanted)) {
return mostWanted;
}
}
return PGPainless.getPolicy().getSymmetricKeyEncryptionAlgorithmPolicy().getDefaultSymmetricKeyAlgorithm();
}

View file

@ -32,6 +32,7 @@ import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
import org.pgpainless.implementation.ImplementationFactory;
import org.pgpainless.key.SubkeyIdentifier;
import org.pgpainless.key.info.KeyRingInfo;
import org.pgpainless.key.info.KeyView;
import org.pgpainless.util.Passphrase;
/**
@ -66,6 +67,7 @@ public class EncryptionOptions {
private final Set<PGPKeyEncryptionMethodGenerator> encryptionMethods = new LinkedHashSet<>();
private final Set<SubkeyIdentifier> encryptionKeys = new LinkedHashSet<>();
private final Map<SubkeyIdentifier, KeyRingInfo> keyRingInfo = new HashMap<>();
private final Map<SubkeyIdentifier, KeyView> keyViews = new HashMap<>();
private final EncryptionKeySelector encryptionKeySelector = encryptToFirstSubkey();
private SymmetricKeyAlgorithm encryptionAlgorithmOverride = null;
@ -131,6 +133,9 @@ public class EncryptionOptions {
}
for (PGPPublicKey encryptionSubkey : encryptionSubkeys) {
SubkeyIdentifier keyId = new SubkeyIdentifier(key, encryptionSubkey.getKeyID());
keyRingInfo.put(keyId, info);
keyViews.put(keyId, new KeyView.ViaUserId(info, keyId, userId));
addRecipientKey(key, encryptionSubkey);
}
@ -162,6 +167,9 @@ public class EncryptionOptions {
}
for (PGPPublicKey encryptionSubkey : encryptionSubkeys) {
SubkeyIdentifier keyId = new SubkeyIdentifier(key, encryptionSubkey.getKeyID());
keyRingInfo.put(keyId, info);
keyViews.put(keyId, new KeyView.ViaKeyId(info, keyId));
addRecipientKey(key, encryptionSubkey);
}
@ -204,14 +212,22 @@ public class EncryptionOptions {
return this;
}
public Set<PGPKeyEncryptionMethodGenerator> getEncryptionMethods() {
Set<PGPKeyEncryptionMethodGenerator> getEncryptionMethods() {
return new HashSet<>(encryptionMethods);
}
Map<SubkeyIdentifier, KeyRingInfo> getKeyRingInfo() {
return new HashMap<>(keyRingInfo);
}
public Set<SubkeyIdentifier> getEncryptionKeyIdentifiers() {
return new HashSet<>(encryptionKeys);
}
public Map<SubkeyIdentifier, KeyView> getKeyViews() {
return new HashMap<>(keyViews);
}
public SymmetricKeyAlgorithm getEncryptionAlgorithmOverride() {
return encryptionAlgorithmOverride;
}

View file

@ -0,0 +1,87 @@
/*
* Copyright 2021 Paul Schaub.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.pgpainless.key.info;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import org.bouncycastle.openpgp.PGPSignature;
import org.pgpainless.algorithm.CompressionAlgorithm;
import org.pgpainless.algorithm.HashAlgorithm;
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
import org.pgpainless.key.SubkeyIdentifier;
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
public abstract class KeyView {
protected final KeyRingInfo info;
protected final SubkeyIdentifier key;
public KeyView(KeyRingInfo info, SubkeyIdentifier key) {
this.info = info;
this.key = key;
}
public abstract PGPSignature getSignatureWithPreferences();
public List<SymmetricKeyAlgorithm> getPreferredSymmetricKeyAlgorithms() {
List<SymmetricKeyAlgorithm> algos = SignatureSubpacketsUtil.parsePreferredSymmetricKeyAlgorithms(getSignatureWithPreferences());
return new ArrayList<>(new LinkedHashSet<>(algos)); // remove duplicates
}
public List<HashAlgorithm> getPreferredHashAlgorithms() {
List<HashAlgorithm> algos = SignatureSubpacketsUtil.parsePreferredHashAlgorithms(getSignatureWithPreferences());
return new ArrayList<>(new LinkedHashSet<>(algos)); // remove duplicates
}
public List<CompressionAlgorithm> getPreferredCompressionAlgorithms() {
List<CompressionAlgorithm> algos = SignatureSubpacketsUtil.parsePreferredCompressionAlgorithms(getSignatureWithPreferences());
return new ArrayList<>(new LinkedHashSet<>(algos)); // remove duplicates
}
public static class ViaUserId extends KeyView {
private final String userId;
public ViaUserId(KeyRingInfo info, SubkeyIdentifier key, String userId) {
super(info, key);
this.userId = userId;
}
@Override
public PGPSignature getSignatureWithPreferences() {
return info.getLatestUserIdCertification(userId);
}
}
public static class ViaKeyId extends KeyView {
public ViaKeyId(KeyRingInfo info, SubkeyIdentifier key) {
super(info, key);
}
@Override
public PGPSignature getSignatureWithPreferences() {
PGPSignature signature = info.getLatestDirectKeySelfSignature();
if (signature != null) {
return signature;
}
return info.getLatestUserIdCertification(info.getPrimaryUserId());
}
}
}