mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-14 16:32:06 +01:00
Add and test GnuDummyKeyUtil
This commit is contained in:
parent
0f9507f713
commit
48d468c310
5 changed files with 427 additions and 0 deletions
|
@ -0,0 +1,24 @@
|
|||
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.key.gnu_dummy_s2k;
|
||||
|
||||
import org.bouncycastle.bcpg.S2K;
|
||||
|
||||
public enum GNUExtension {
|
||||
|
||||
NO_PRIVATE_KEY(S2K.GNU_PROTECTION_MODE_NO_PRIVATE_KEY),
|
||||
DIVERT_TO_CARD(S2K.GNU_PROTECTION_MODE_DIVERT_TO_CARD),
|
||||
;
|
||||
|
||||
private final int id;
|
||||
|
||||
GNUExtension(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.key.gnu_dummy_s2k;
|
||||
|
||||
import org.bouncycastle.bcpg.PublicKeyPacket;
|
||||
import org.bouncycastle.bcpg.S2K;
|
||||
import org.bouncycastle.bcpg.SecretKeyPacket;
|
||||
import org.bouncycastle.bcpg.SecretSubkeyPacket;
|
||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public final class GnuDummyKeyUtil {
|
||||
|
||||
private GnuDummyKeyUtil() {
|
||||
|
||||
}
|
||||
|
||||
public static Builder modify(PGPSecretKeyRing secretKeys) {
|
||||
return new Builder(secretKeys);
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
|
||||
private final PGPSecretKeyRing keys;
|
||||
|
||||
private Builder(PGPSecretKeyRing keys) {
|
||||
this.keys = keys;
|
||||
}
|
||||
|
||||
public PGPSecretKeyRing removePrivateKeys(KeyFilter filter) {
|
||||
return doIt(GNUExtension.NO_PRIVATE_KEY, null, filter);
|
||||
}
|
||||
|
||||
public PGPSecretKeyRing divertPrivateKeysToCard(KeyFilter filter) {
|
||||
return divertPrivateKeysToCard(filter, new byte[16]);
|
||||
}
|
||||
|
||||
public PGPSecretKeyRing divertPrivateKeysToCard(KeyFilter filter, byte[] cardSerialNumber) {
|
||||
return doIt(GNUExtension.DIVERT_TO_CARD, cardSerialNumber, filter);
|
||||
}
|
||||
|
||||
private PGPSecretKeyRing doIt(GNUExtension extension, byte[] serial, KeyFilter filter) {
|
||||
byte[] encodedSerial = serial != null ? encodeSerial(serial) : null;
|
||||
S2K s2k = extensionToS2K(extension);
|
||||
|
||||
List<PGPSecretKey> secretKeyList = new ArrayList<>();
|
||||
for (PGPSecretKey secretKey : keys) {
|
||||
if (!filter.filter(secretKey.getKeyID())) {
|
||||
// No conversion, do not modify subkey
|
||||
secretKeyList.add(secretKey);
|
||||
continue;
|
||||
}
|
||||
|
||||
PublicKeyPacket publicKeyPacket = secretKey.getPublicKey().getPublicKeyPacket();
|
||||
if (secretKey.isMasterKey()) {
|
||||
SecretKeyPacket keyPacket = new SecretKeyPacket(publicKeyPacket,
|
||||
0, 255, s2k, null, encodedSerial);
|
||||
PGPSecretKey onCard = new PGPSecretKey(keyPacket, secretKey.getPublicKey());
|
||||
secretKeyList.add(onCard);
|
||||
} else {
|
||||
SecretSubkeyPacket keyPacket = new SecretSubkeyPacket(publicKeyPacket,
|
||||
0, 255, s2k, null, encodedSerial);
|
||||
PGPSecretKey onCard = new PGPSecretKey(keyPacket, secretKey.getPublicKey());
|
||||
secretKeyList.add(onCard);
|
||||
}
|
||||
}
|
||||
|
||||
PGPSecretKeyRing gnuDummyKey = new PGPSecretKeyRing(secretKeyList);
|
||||
return gnuDummyKey;
|
||||
}
|
||||
|
||||
private byte[] encodeSerial(byte[] serial) {
|
||||
byte[] encoded = new byte[serial.length + 1];
|
||||
encoded[0] = 0x10;
|
||||
System.arraycopy(serial, 0, encoded, 1, serial.length);
|
||||
return encoded;
|
||||
}
|
||||
|
||||
private S2K extensionToS2K(GNUExtension extension) {
|
||||
S2K s2k = S2K.gnuDummyS2K(extension == GNUExtension.DIVERT_TO_CARD ?
|
||||
S2K.GNUDummyParams.divertToCard() : S2K.GNUDummyParams.noPrivateKey());
|
||||
return s2k;
|
||||
}
|
||||
}
|
||||
|
||||
public interface KeyFilter {
|
||||
|
||||
/**
|
||||
* Return true, if the given key should be selected, false otherwise.
|
||||
*
|
||||
* @param keyId id of the key
|
||||
* @return select
|
||||
*/
|
||||
boolean filter(long keyId);
|
||||
|
||||
static KeyFilter any() {
|
||||
return keyId -> true;
|
||||
}
|
||||
|
||||
static KeyFilter only(long onlyKeyId) {
|
||||
return keyId -> keyId == onlyKeyId;
|
||||
}
|
||||
|
||||
static KeyFilter selected(Collection<Long> ids) {
|
||||
return keyId -> ids.contains(keyId);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/**
|
||||
* Utility classes related to creating keys with GNU DUMMY S2K values.
|
||||
*/
|
||||
package org.pgpainless.key.gnu_dummy_s2k;
|
|
@ -0,0 +1,82 @@
|
|||
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.decryption_verification;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.pgpainless.PGPainless;
|
||||
import org.pgpainless.key.SubkeyIdentifier;
|
||||
import org.pgpainless.key.gnu_dummy_s2k.GnuDummyKeyUtil;
|
||||
import org.pgpainless.key.util.KeyIdUtil;
|
||||
|
||||
public class HardwareSecurityTest {
|
||||
|
||||
private static final String KEY = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
|
||||
"Version: PGPainless\n" +
|
||||
"Comment: DE2E 9AB2 6650 8191 53E7 D599 C176 507F 2B5D 43B3\n" +
|
||||
"Comment: Alice <alice@pgpainless.org>\n" +
|
||||
"\n" +
|
||||
"lFgEY1vjgRYJKwYBBAHaRw8BAQdAXjLoPTOIOdvlFT2Nt3rcvLTVx5ujPBGghZ5S\n" +
|
||||
"D5tEnyoAAP0fAUJTiPrxZYdzs6MP0KFo+Nmr/wb1PJHTkzmYpt4wkRKBtBxBbGlj\n" +
|
||||
"ZSA8YWxpY2VAcGdwYWlubGVzcy5vcmc+iI8EExYKAEEFAmNb44EJEMF2UH8rXUOz\n" +
|
||||
"FiEE3i6asmZQgZFT59WZwXZQfytdQ7MCngECmwEFFgIDAQAECwkIBwUVCgkICwKZ\n" +
|
||||
"AQAAHLYA/AgW+YrpU+UqrwX2dhY6RAfgHTTMU89RHjaTHJx8pLrBAP4gthGof00a\n" +
|
||||
"XEjwTWteDOO049SIp2AUfj9deJqtrQcHD5xdBGNb44ESCisGAQQBl1UBBQEBB0DN\n" +
|
||||
"vUT3awa3YLmwf41LRpPrm7B87AOHfYIP8S9QJ4GDJgMBCAcAAP9bwlSaF+lti8JY\n" +
|
||||
"qKFO3qt3ZYQMu1l/LRBle89ZB4zD+BDOiHUEGBYKAB0FAmNb44ECngECmwwFFgID\n" +
|
||||
"AQAECwkIBwUVCgkICwAKCRDBdlB/K11Ds/TsAP9kvpUrCWnrWGq+a9n1CqEfCMX5\n" +
|
||||
"cT+qzrwNf+J0L22KowD+M9SVO0qssiAqutLE9h9dGYLbEiFvsHzK3WSnjKYbIgac\n" +
|
||||
"WARjW+OBFgkrBgEEAdpHDwEBB0BCPh8M5TnXSmG6Ygwp4j5RR4u3hmxl8CYjX4h/\n" +
|
||||
"XtvvNwAA/RP04coSrLHVI6vUfbJk4MhWYeyhJBRYY0vGp7yq+wVtEpKI1QQYFgoA\n" +
|
||||
"fQUCY1vjgQKeAQKbAgUWAgMBAAQLCQgHBRUKCQgLXyAEGRYKAAYFAmNb44EACgkQ\n" +
|
||||
"mlozJSF7rXQW+AD/TA3YBxTd+YbBSwfgqzWNbfT9BBcFrdn3uPCsbvfmqXoA/3oj\n" +
|
||||
"oupkgoaXesrGxn2k9hW9/GBXSvNcgY2txZ6/oYoIAAoJEMF2UH8rXUOziZ4A/0Xl\n" +
|
||||
"xSZJWmkRpBh5AO8Cnqosz6j947IYAxS16ay+sIOHAP9aN9CUNJIIdHnHdFHO4GZz\n" +
|
||||
"ejjknn4wt8NVJP97JxlnBQ==\n" +
|
||||
"=qSQb\n" +
|
||||
"-----END PGP PRIVATE KEY BLOCK-----";
|
||||
|
||||
@Test
|
||||
public void testGetSingleIdOfHardwareBackedKey() throws IOException {
|
||||
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(KEY);
|
||||
assertTrue(HardwareSecurity.getIdsOfHardwareBackedKeys(secretKeys).isEmpty());
|
||||
long encryptionKeyId = KeyIdUtil.fromLongKeyId("0AAD8F5891262F50");
|
||||
|
||||
PGPSecretKeyRing withHardwareBackedEncryptionKey = GnuDummyKeyUtil.modify(secretKeys)
|
||||
.divertPrivateKeysToCard(GnuDummyKeyUtil.KeyFilter.only(encryptionKeyId));
|
||||
|
||||
Set<SubkeyIdentifier> hardwareBackedKeys = HardwareSecurity
|
||||
.getIdsOfHardwareBackedKeys(withHardwareBackedEncryptionKey);
|
||||
assertEquals(Collections.singleton(new SubkeyIdentifier(secretKeys, encryptionKeyId)), hardwareBackedKeys);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetIdsOfFullyHardwareBackedKey() throws IOException {
|
||||
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(KEY);
|
||||
assertTrue(HardwareSecurity.getIdsOfHardwareBackedKeys(secretKeys).isEmpty());
|
||||
|
||||
PGPSecretKeyRing withHardwareBackedEncryptionKey = GnuDummyKeyUtil.modify(secretKeys)
|
||||
.divertPrivateKeysToCard(GnuDummyKeyUtil.KeyFilter.any());
|
||||
Set<SubkeyIdentifier> expected = new HashSet<>();
|
||||
for (PGPSecretKey key : secretKeys) {
|
||||
expected.add(new SubkeyIdentifier(secretKeys, key.getKeyID()));
|
||||
}
|
||||
|
||||
Set<SubkeyIdentifier> hardwareBackedKeys = HardwareSecurity
|
||||
.getIdsOfHardwareBackedKeys(withHardwareBackedEncryptionKey);
|
||||
|
||||
assertEquals(expected, hardwareBackedKeys);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,199 @@
|
|||
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.pgpainless.key.gnu_dummy_s2k;
|
||||
|
||||
import org.bouncycastle.bcpg.S2K;
|
||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.pgpainless.PGPainless;
|
||||
import org.pgpainless.key.util.KeyIdUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class GnuDummyKeyUtilTest {
|
||||
// normal, non-hw-backed key
|
||||
private static final String FULL_KEY = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
|
||||
"Version: PGPainless\n" +
|
||||
"Comment: 01FD AB6C E04A 5078 79FE 4A18 C312 C97D A9F7 6A4F\n" +
|
||||
"Comment: Hardy Hardware <hardy@hard.ware>\n" +
|
||||
"\n" +
|
||||
"lFgEY1vSiBYJKwYBBAHaRw8BAQdAQ58lZn/HOtg+1b1KS18odyQ6M4LaDdbJAyRf\n" +
|
||||
"eBwCeTQAAPwJN+Xmr0jjN7RA9jgqXnxC/rcWHmdp/j9NdEd7K2Wbxw/rtCBIYXJk\n" +
|
||||
"eSBIYXJkd2FyZSA8aGFyZHlAaGFyZC53YXJlPoiPBBMWCgBBBQJjW9KICRDDEsl9\n" +
|
||||
"qfdqTxYhBAH9q2zgSlB4ef5KGMMSyX2p92pPAp4BApsBBRYCAwEABAsJCAcFFQoJ\n" +
|
||||
"CAsCmQEAAPk2AP922T5TQ7hukFlpxX3ThMhieJnECGY5Eqt5U0/vEY1XdgD/eE1M\n" +
|
||||
"l9qqx6QGcaNKe8deMe3EhTant6mS9tqMHp2/3gmcXQRjW9KIEgorBgEEAZdVAQUB\n" +
|
||||
"AQdAVXBLNvNmFh9KX6iLmdNJM28Zc9PGnzEoAD9+T4p0lDwDAQgHAAD/fw9hnzeH\n" +
|
||||
"VtBaHi6efXvnc4rdVj8zWk0LKo1clFd3bTAN+oh1BBgWCgAdBQJjW9KIAp4BApsM\n" +
|
||||
"BRYCAwEABAsJCAcFFQoJCAsACgkQwxLJfan3ak/JyQD9GBj0vjtYZAf5Fi0eEKdi\n" +
|
||||
"Ags0yZrQPkMs6eL+83te770A/jG0DeJy+88fOfWTj+mixO98PZPnQ0MybWC/1QUT\n" +
|
||||
"vP0BnFgEY1vSiBYJKwYBBAHaRw8BAQdAvSYTD60t8vx10dSEBACUoIfVCpeOB30D\n" +
|
||||
"6nfwJtbDT0YAAQCgnCsN9iX7s2TQd8NPggWs4QdhaFpb6olt3SlAvUy/wRBDiNUE\n" +
|
||||
"GBYKAH0FAmNb0ogCngECmwIFFgIDAQAECwkIBwUVCgkIC18gBBkWCgAGBQJjW9KI\n" +
|
||||
"AAoJEJQCL6VtwFtJDmMBAKqsGfRFQxJXyPgugWBgEaO5lt9fMM0yUxa76cmSWe5f\n" +
|
||||
"AQD2oLSEW1GOgIs64+Z3gvtXopmeupT09HhI7ger98zDAwAKCRDDEsl9qfdqTwR6\n" +
|
||||
"AP9Xftw8xZ7/MWhYImk/xheqPy07K4qo3T1pGKUvUqjWQQEAhE3r0oTcJn+KVCwG\n" +
|
||||
"jF6AYiLOzO/R1x5bSlYD3FeJ3Qo=\n" +
|
||||
"=+vXp\n" +
|
||||
"-----END PGP PRIVATE KEY BLOCK-----\n";
|
||||
|
||||
private static final long primaryKeyId = KeyIdUtil.fromLongKeyId("C312C97DA9F76A4F");
|
||||
private static final long encryptionKeyId = KeyIdUtil.fromLongKeyId("6924D066714CE8C6");
|
||||
private static final long signatureKeyId = KeyIdUtil.fromLongKeyId("94022FA56DC05B49");
|
||||
private static final byte[] cardSerial = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
|
||||
|
||||
public static final String ALL_KEYS_ON_CARD = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
|
||||
"Version: PGPainless\n" +
|
||||
"Comment: 01FD AB6C E04A 5078 79FE 4A18 C312 C97D A9F7 6A4F\n" +
|
||||
"Comment: Hardy Hardware <hardy@hard.ware>\n" +
|
||||
"\n" +
|
||||
"lEwEY1vSiBYJKwYBBAHaRw8BAQdAQ58lZn/HOtg+1b1KS18odyQ6M4LaDdbJAyRf\n" +
|
||||
"eBwCeTT/AGUAR05VAhAAAQIDBAUGBwgJCgsMDQ4PtCBIYXJkeSBIYXJkd2FyZSA8\n" +
|
||||
"aGFyZHlAaGFyZC53YXJlPoiPBBMWCgBBBQJjW9KICRDDEsl9qfdqTxYhBAH9q2zg\n" +
|
||||
"SlB4ef5KGMMSyX2p92pPAp4BApsBBRYCAwEABAsJCAcFFQoJCAsCmQEAAPk2AP92\n" +
|
||||
"2T5TQ7hukFlpxX3ThMhieJnECGY5Eqt5U0/vEY1XdgD/eE1Ml9qqx6QGcaNKe8de\n" +
|
||||
"Me3EhTant6mS9tqMHp2/3gmcUQRjW9KIEgorBgEEAZdVAQUBAQdAVXBLNvNmFh9K\n" +
|
||||
"X6iLmdNJM28Zc9PGnzEoAD9+T4p0lDwDAQgH/wBlAEdOVQIQAAECAwQFBgcICQoL\n" +
|
||||
"DA0OD4h1BBgWCgAdBQJjW9KIAp4BApsMBRYCAwEABAsJCAcFFQoJCAsACgkQwxLJ\n" +
|
||||
"fan3ak/JyQD9GBj0vjtYZAf5Fi0eEKdiAgs0yZrQPkMs6eL+83te770A/jG0DeJy\n" +
|
||||
"+88fOfWTj+mixO98PZPnQ0MybWC/1QUTvP0BnEwEY1vSiBYJKwYBBAHaRw8BAQdA\n" +
|
||||
"vSYTD60t8vx10dSEBACUoIfVCpeOB30D6nfwJtbDT0b/AGUAR05VAhAAAQIDBAUG\n" +
|
||||
"BwgJCgsMDQ4PiNUEGBYKAH0FAmNb0ogCngECmwIFFgIDAQAECwkIBwUVCgkIC18g\n" +
|
||||
"BBkWCgAGBQJjW9KIAAoJEJQCL6VtwFtJDmMBAKqsGfRFQxJXyPgugWBgEaO5lt9f\n" +
|
||||
"MM0yUxa76cmSWe5fAQD2oLSEW1GOgIs64+Z3gvtXopmeupT09HhI7ger98zDAwAK\n" +
|
||||
"CRDDEsl9qfdqTwR6AP9Xftw8xZ7/MWhYImk/xheqPy07K4qo3T1pGKUvUqjWQQEA\n" +
|
||||
"hE3r0oTcJn+KVCwGjF6AYiLOzO/R1x5bSlYD3FeJ3Qo=\n" +
|
||||
"=wsFa\n" +
|
||||
"-----END PGP PRIVATE KEY BLOCK-----";
|
||||
|
||||
public static final String PRIMARY_KEY_ON_CARD = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
|
||||
"Version: PGPainless\n" +
|
||||
"Comment: 01FD AB6C E04A 5078 79FE 4A18 C312 C97D A9F7 6A4F\n" +
|
||||
"Comment: Hardy Hardware <hardy@hard.ware>\n" +
|
||||
"\n" +
|
||||
"lEwEY1vSiBYJKwYBBAHaRw8BAQdAQ58lZn/HOtg+1b1KS18odyQ6M4LaDdbJAyRf\n" +
|
||||
"eBwCeTT/AGUAR05VAhAAAQIDBAUGBwgJCgsMDQ4PtCBIYXJkeSBIYXJkd2FyZSA8\n" +
|
||||
"aGFyZHlAaGFyZC53YXJlPoiPBBMWCgBBBQJjW9KICRDDEsl9qfdqTxYhBAH9q2zg\n" +
|
||||
"SlB4ef5KGMMSyX2p92pPAp4BApsBBRYCAwEABAsJCAcFFQoJCAsCmQEAAPk2AP92\n" +
|
||||
"2T5TQ7hukFlpxX3ThMhieJnECGY5Eqt5U0/vEY1XdgD/eE1Ml9qqx6QGcaNKe8de\n" +
|
||||
"Me3EhTant6mS9tqMHp2/3gmcXQRjW9KIEgorBgEEAZdVAQUBAQdAVXBLNvNmFh9K\n" +
|
||||
"X6iLmdNJM28Zc9PGnzEoAD9+T4p0lDwDAQgHAAD/fw9hnzeHVtBaHi6efXvnc4rd\n" +
|
||||
"Vj8zWk0LKo1clFd3bTAN+oh1BBgWCgAdBQJjW9KIAp4BApsMBRYCAwEABAsJCAcF\n" +
|
||||
"FQoJCAsACgkQwxLJfan3ak/JyQD9GBj0vjtYZAf5Fi0eEKdiAgs0yZrQPkMs6eL+\n" +
|
||||
"83te770A/jG0DeJy+88fOfWTj+mixO98PZPnQ0MybWC/1QUTvP0BnFgEY1vSiBYJ\n" +
|
||||
"KwYBBAHaRw8BAQdAvSYTD60t8vx10dSEBACUoIfVCpeOB30D6nfwJtbDT0YAAQCg\n" +
|
||||
"nCsN9iX7s2TQd8NPggWs4QdhaFpb6olt3SlAvUy/wRBDiNUEGBYKAH0FAmNb0ogC\n" +
|
||||
"ngECmwIFFgIDAQAECwkIBwUVCgkIC18gBBkWCgAGBQJjW9KIAAoJEJQCL6VtwFtJ\n" +
|
||||
"DmMBAKqsGfRFQxJXyPgugWBgEaO5lt9fMM0yUxa76cmSWe5fAQD2oLSEW1GOgIs6\n" +
|
||||
"4+Z3gvtXopmeupT09HhI7ger98zDAwAKCRDDEsl9qfdqTwR6AP9Xftw8xZ7/MWhY\n" +
|
||||
"Imk/xheqPy07K4qo3T1pGKUvUqjWQQEAhE3r0oTcJn+KVCwGjF6AYiLOzO/R1x5b\n" +
|
||||
"SlYD3FeJ3Qo=\n" +
|
||||
"=s+B1\n" +
|
||||
"-----END PGP PRIVATE KEY BLOCK-----";
|
||||
|
||||
public static final String ENCRYPTION_KEY_ON_CARD = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
|
||||
"Version: PGPainless\n" +
|
||||
"Comment: 01FD AB6C E04A 5078 79FE 4A18 C312 C97D A9F7 6A4F\n" +
|
||||
"Comment: Hardy Hardware <hardy@hard.ware>\n" +
|
||||
"\n" +
|
||||
"lFgEY1vSiBYJKwYBBAHaRw8BAQdAQ58lZn/HOtg+1b1KS18odyQ6M4LaDdbJAyRf\n" +
|
||||
"eBwCeTQAAPwJN+Xmr0jjN7RA9jgqXnxC/rcWHmdp/j9NdEd7K2Wbxw/rtCBIYXJk\n" +
|
||||
"eSBIYXJkd2FyZSA8aGFyZHlAaGFyZC53YXJlPoiPBBMWCgBBBQJjW9KICRDDEsl9\n" +
|
||||
"qfdqTxYhBAH9q2zgSlB4ef5KGMMSyX2p92pPAp4BApsBBRYCAwEABAsJCAcFFQoJ\n" +
|
||||
"CAsCmQEAAPk2AP922T5TQ7hukFlpxX3ThMhieJnECGY5Eqt5U0/vEY1XdgD/eE1M\n" +
|
||||
"l9qqx6QGcaNKe8deMe3EhTant6mS9tqMHp2/3gmcUQRjW9KIEgorBgEEAZdVAQUB\n" +
|
||||
"AQdAVXBLNvNmFh9KX6iLmdNJM28Zc9PGnzEoAD9+T4p0lDwDAQgH/wBlAEdOVQIQ\n" +
|
||||
"AAECAwQFBgcICQoLDA0OD4h1BBgWCgAdBQJjW9KIAp4BApsMBRYCAwEABAsJCAcF\n" +
|
||||
"FQoJCAsACgkQwxLJfan3ak/JyQD9GBj0vjtYZAf5Fi0eEKdiAgs0yZrQPkMs6eL+\n" +
|
||||
"83te770A/jG0DeJy+88fOfWTj+mixO98PZPnQ0MybWC/1QUTvP0BnFgEY1vSiBYJ\n" +
|
||||
"KwYBBAHaRw8BAQdAvSYTD60t8vx10dSEBACUoIfVCpeOB30D6nfwJtbDT0YAAQCg\n" +
|
||||
"nCsN9iX7s2TQd8NPggWs4QdhaFpb6olt3SlAvUy/wRBDiNUEGBYKAH0FAmNb0ogC\n" +
|
||||
"ngECmwIFFgIDAQAECwkIBwUVCgkIC18gBBkWCgAGBQJjW9KIAAoJEJQCL6VtwFtJ\n" +
|
||||
"DmMBAKqsGfRFQxJXyPgugWBgEaO5lt9fMM0yUxa76cmSWe5fAQD2oLSEW1GOgIs6\n" +
|
||||
"4+Z3gvtXopmeupT09HhI7ger98zDAwAKCRDDEsl9qfdqTwR6AP9Xftw8xZ7/MWhY\n" +
|
||||
"Imk/xheqPy07K4qo3T1pGKUvUqjWQQEAhE3r0oTcJn+KVCwGjF6AYiLOzO/R1x5b\n" +
|
||||
"SlYD3FeJ3Qo=\n" +
|
||||
"=TPAl\n" +
|
||||
"-----END PGP PRIVATE KEY BLOCK-----";
|
||||
|
||||
public static final String SIGNATURE_KEY_ON_CARD = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
|
||||
"Version: PGPainless\n" +
|
||||
"Comment: 01FD AB6C E04A 5078 79FE 4A18 C312 C97D A9F7 6A4F\n" +
|
||||
"Comment: Hardy Hardware <hardy@hard.ware>\n" +
|
||||
"\n" +
|
||||
"lFgEY1vSiBYJKwYBBAHaRw8BAQdAQ58lZn/HOtg+1b1KS18odyQ6M4LaDdbJAyRf\n" +
|
||||
"eBwCeTQAAPwJN+Xmr0jjN7RA9jgqXnxC/rcWHmdp/j9NdEd7K2Wbxw/rtCBIYXJk\n" +
|
||||
"eSBIYXJkd2FyZSA8aGFyZHlAaGFyZC53YXJlPoiPBBMWCgBBBQJjW9KICRDDEsl9\n" +
|
||||
"qfdqTxYhBAH9q2zgSlB4ef5KGMMSyX2p92pPAp4BApsBBRYCAwEABAsJCAcFFQoJ\n" +
|
||||
"CAsCmQEAAPk2AP922T5TQ7hukFlpxX3ThMhieJnECGY5Eqt5U0/vEY1XdgD/eE1M\n" +
|
||||
"l9qqx6QGcaNKe8deMe3EhTant6mS9tqMHp2/3gmcXQRjW9KIEgorBgEEAZdVAQUB\n" +
|
||||
"AQdAVXBLNvNmFh9KX6iLmdNJM28Zc9PGnzEoAD9+T4p0lDwDAQgHAAD/fw9hnzeH\n" +
|
||||
"VtBaHi6efXvnc4rdVj8zWk0LKo1clFd3bTAN+oh1BBgWCgAdBQJjW9KIAp4BApsM\n" +
|
||||
"BRYCAwEABAsJCAcFFQoJCAsACgkQwxLJfan3ak/JyQD9GBj0vjtYZAf5Fi0eEKdi\n" +
|
||||
"Ags0yZrQPkMs6eL+83te770A/jG0DeJy+88fOfWTj+mixO98PZPnQ0MybWC/1QUT\n" +
|
||||
"vP0BnEwEY1vSiBYJKwYBBAHaRw8BAQdAvSYTD60t8vx10dSEBACUoIfVCpeOB30D\n" +
|
||||
"6nfwJtbDT0b/AGUAR05VAhAAAQIDBAUGBwgJCgsMDQ4PiNUEGBYKAH0FAmNb0ogC\n" +
|
||||
"ngECmwIFFgIDAQAECwkIBwUVCgkIC18gBBkWCgAGBQJjW9KIAAoJEJQCL6VtwFtJ\n" +
|
||||
"DmMBAKqsGfRFQxJXyPgugWBgEaO5lt9fMM0yUxa76cmSWe5fAQD2oLSEW1GOgIs6\n" +
|
||||
"4+Z3gvtXopmeupT09HhI7ger98zDAwAKCRDDEsl9qfdqTwR6AP9Xftw8xZ7/MWhY\n" +
|
||||
"Imk/xheqPy07K4qo3T1pGKUvUqjWQQEAhE3r0oTcJn+KVCwGjF6AYiLOzO/R1x5b\n" +
|
||||
"SlYD3FeJ3Qo=\n" +
|
||||
"=p8I9\n" +
|
||||
"-----END PGP PRIVATE KEY BLOCK-----";
|
||||
|
||||
@Test
|
||||
public void testMoveAllKeysToCard() throws IOException {
|
||||
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(FULL_KEY);
|
||||
PGPSecretKeyRing expected = PGPainless.readKeyRing().secretKeyRing(ALL_KEYS_ON_CARD);
|
||||
|
||||
PGPSecretKeyRing onCard = GnuDummyKeyUtil.modify(secretKeys)
|
||||
.divertPrivateKeysToCard(GnuDummyKeyUtil.KeyFilter.any(), cardSerial);
|
||||
|
||||
for (PGPSecretKey key : onCard) {
|
||||
assertEquals(255, key.getS2KUsage());
|
||||
S2K s2K = key.getS2K();
|
||||
assertEquals(S2K.GNU_PROTECTION_MODE_DIVERT_TO_CARD, s2K.getProtectionMode());
|
||||
}
|
||||
|
||||
assertArrayEquals(expected.getEncoded(), onCard.getEncoded());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMovePrimaryKeyToCard() throws IOException {
|
||||
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(FULL_KEY);
|
||||
PGPSecretKeyRing expected = PGPainless.readKeyRing().secretKeyRing(PRIMARY_KEY_ON_CARD);
|
||||
|
||||
PGPSecretKeyRing onCard = GnuDummyKeyUtil.modify(secretKeys)
|
||||
.divertPrivateKeysToCard(GnuDummyKeyUtil.KeyFilter.only(primaryKeyId), cardSerial);
|
||||
|
||||
assertArrayEquals(expected.getEncoded(), onCard.getEncoded());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveEncryptionKeyToCard() throws IOException {
|
||||
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(FULL_KEY);
|
||||
PGPSecretKeyRing expected = PGPainless.readKeyRing().secretKeyRing(ENCRYPTION_KEY_ON_CARD);
|
||||
|
||||
PGPSecretKeyRing onCard = GnuDummyKeyUtil.modify(secretKeys)
|
||||
.divertPrivateKeysToCard(GnuDummyKeyUtil.KeyFilter.only(encryptionKeyId), cardSerial);
|
||||
|
||||
assertArrayEquals(expected.getEncoded(), onCard.getEncoded());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveSigningKeyToCard() throws IOException {
|
||||
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(FULL_KEY);
|
||||
PGPSecretKeyRing expected = PGPainless.readKeyRing().secretKeyRing(SIGNATURE_KEY_ON_CARD);
|
||||
|
||||
PGPSecretKeyRing onCard = GnuDummyKeyUtil.modify(secretKeys)
|
||||
.divertPrivateKeysToCard(GnuDummyKeyUtil.KeyFilter.only(signatureKeyId), cardSerial);
|
||||
|
||||
assertArrayEquals(expected.getEncoded(), onCard.getEncoded());
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue