diff --git a/app/build.gradle b/app/build.gradle index 57661d0..1dbf468 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,7 +3,7 @@ plugins { id 'com.palantir.git-version' } -group 'org.egothor' +group='org.egothor' dependencies { implementation 'org.apache.commons:commons-text' diff --git a/lib/build.gradle b/lib/build.gradle index 043bdef..a52b1dd 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -3,7 +3,7 @@ plugins { id 'com.palantir.git-version' } -group 'org.egothor' +group='org.egothor' dependencies { implementation 'org.bouncycastle:bcpkix-jdk18on' diff --git a/lib/src/main/java/zeroecho/core/storage/KeyringStore.java b/lib/src/main/java/zeroecho/core/storage/KeyringStore.java index 37238f7..2990c35 100644 --- a/lib/src/main/java/zeroecho/core/storage/KeyringStore.java +++ b/lib/src/main/java/zeroecho/core/storage/KeyringStore.java @@ -108,12 +108,18 @@ import zeroecho.core.spec.AlgorithmKeySpec; * PublicKey pub = reloaded.getPublic("site-signing"); * } */ -public final class KeyringStore { +public final class KeyringStore { // NOPMD private static final String MAGIC_HEADER = "# KeyringStore v1"; private static final String ENTRY_MARKER = "@entry"; private static final String PREFIX_SPEC = "s."; // marks spec payload keys + /** Suffix used for persisted public key aliases. */ + private static final String SUFFIX_PUBLIC = ".pub"; + + /** Suffix used for persisted private key aliases. */ + private static final String SUFFIX_PRIVATE = ".priv"; + private final Map byAlias = new LinkedHashMap<>(); /** @@ -163,7 +169,7 @@ public final class KeyringStore { * @throws IllegalArgumentException if any argument is invalid */ public void putPublic(String alias, String algorithmId, AlgorithmKeySpec importSpec) { - put(alias, algorithmId, Record.Kind.PUBLIC_KEY, importSpec); + put(withPublicSuffix(alias), algorithmId, Record.Kind.PUBLIC_KEY, importSpec); } /** @@ -175,7 +181,7 @@ public final class KeyringStore { * @throws IllegalArgumentException if any argument is invalid */ public void putPrivate(String alias, String algorithmId, AlgorithmKeySpec importSpec) { - put(alias, algorithmId, Record.Kind.PRIVATE_KEY, importSpec); + put(withPrivateSuffix(alias), algorithmId, Record.Kind.PRIVATE_KEY, importSpec); } /** @@ -197,7 +203,13 @@ public final class KeyringStore { * @return true if an entry exists for the alias, false otherwise */ public boolean contains(String alias) { - return byAlias.containsKey(alias); + if (alias == null) { + return false; + } + if (byAlias.containsKey(alias)) { + return true; + } + return byAlias.containsKey(withPublicSuffix(alias)) || byAlias.containsKey(withPrivateSuffix(alias)); } /** @@ -206,7 +218,11 @@ public final class KeyringStore { * @return a new list of aliases; the returned list is mutable but independent */ public List aliases() { - return new ArrayList<>(byAlias.keySet()); + List out = new ArrayList<>(byAlias.size()); + for (String a : byAlias.keySet()) { + out.add(stripKnownSuffix(a)); + } + return out; } /** @@ -264,7 +280,7 @@ public final class KeyringStore { * @throws IllegalArgumentException if alias is missing or not a public key */ public PublicWithId getPublicWithId(String alias) throws GeneralSecurityException { - Record r = require(alias, Record.Kind.PUBLIC_KEY); + Record r = require(withPublicSuffix(alias), Record.Kind.PUBLIC_KEY); AlgorithmKeySpec spec = unmarshalSpec(r.specClass, r.specPayload); PublicKey key = CryptoAlgorithms.publicKey(r.algorithm, spec); return new PublicWithId(r.algorithm, key); @@ -280,7 +296,7 @@ public final class KeyringStore { * @throws IllegalArgumentException if alias is missing or not a private key */ public PrivateWithId getPrivateWithId(String alias) throws GeneralSecurityException { - Record r = require(alias, Record.Kind.PRIVATE_KEY); + Record r = require(withPrivateSuffix(alias), Record.Kind.PRIVATE_KEY); AlgorithmKeySpec spec = unmarshalSpec(r.specClass, r.specPayload); PrivateKey key = CryptoAlgorithms.privateKey(r.algorithm, spec); return new PrivateWithId(r.algorithm, key); @@ -319,7 +335,7 @@ public final class KeyringStore { * a public key */ public PublicKey getPublic(String alias) throws GeneralSecurityException { - Record r = require(alias, Record.Kind.PUBLIC_KEY); + Record r = require(withPublicSuffix(alias), Record.Kind.PUBLIC_KEY); AlgorithmKeySpec spec = unmarshalSpec(r.specClass, r.specPayload); return CryptoAlgorithms.publicKey(r.algorithm, spec); } @@ -335,11 +351,44 @@ public final class KeyringStore { * a private key */ public PrivateKey getPrivate(String alias) throws GeneralSecurityException { - Record r = require(alias, Record.Kind.PRIVATE_KEY); + Record r = require(withPrivateSuffix(alias), Record.Kind.PRIVATE_KEY); AlgorithmKeySpec spec = unmarshalSpec(r.specClass, r.specPayload); return CryptoAlgorithms.privateKey(r.algorithm, spec); } + private static String withPublicSuffix(String baseAlias) { + if (baseAlias == null || baseAlias.isBlank()) { + throw new IllegalArgumentException("alias"); + } + if (baseAlias.endsWith(SUFFIX_PUBLIC)) { + return baseAlias; + } + return baseAlias + SUFFIX_PUBLIC; + } + + private static String withPrivateSuffix(String baseAlias) { + if (baseAlias == null || baseAlias.isBlank()) { + throw new IllegalArgumentException("alias"); + } + if (baseAlias.endsWith(SUFFIX_PRIVATE)) { + return baseAlias; + } + return baseAlias + SUFFIX_PRIVATE; + } + + private static String stripKnownSuffix(String alias) { + if (alias == null) { + return null; + } + if (alias.endsWith(SUFFIX_PUBLIC)) { + return alias.substring(0, alias.length() - SUFFIX_PUBLIC.length()); + } + if (alias.endsWith(SUFFIX_PRIVATE)) { + return alias.substring(0, alias.length() - SUFFIX_PRIVATE.length()); + } + return alias; + } + /** * Resolves the secret key bound to the alias. * diff --git a/pki/.classpath b/pki/.classpath index 8ce7b51..961b063 100644 --- a/pki/.classpath +++ b/pki/.classpath @@ -19,13 +19,6 @@ - - - - - - - diff --git a/pki/build.gradle b/pki/build.gradle index b73381d..2c7c5f0 100644 --- a/pki/build.gradle +++ b/pki/build.gradle @@ -3,7 +3,7 @@ plugins { id 'com.palantir.git-version' } -group 'org.egothor' +group='org.egothor' dependencies { implementation 'org.apache.commons:commons-text'