Keyring naming cleanup and deprecation fix

chore: standardize keyring pub/priv naming
chore: prepare for deprecated assignment replacement
This commit is contained in:
2026-03-22 14:30:16 +01:00
parent c922c02fd2
commit 414e812150
5 changed files with 61 additions and 19 deletions

View File

@@ -3,7 +3,7 @@ plugins {
id 'com.palantir.git-version' id 'com.palantir.git-version'
} }
group 'org.egothor' group='org.egothor'
dependencies { dependencies {
implementation 'org.apache.commons:commons-text' implementation 'org.apache.commons:commons-text'

View File

@@ -3,7 +3,7 @@ plugins {
id 'com.palantir.git-version' id 'com.palantir.git-version'
} }
group 'org.egothor' group='org.egothor'
dependencies { dependencies {
implementation 'org.bouncycastle:bcpkix-jdk18on' implementation 'org.bouncycastle:bcpkix-jdk18on'

View File

@@ -108,12 +108,18 @@ import zeroecho.core.spec.AlgorithmKeySpec;
* PublicKey pub = reloaded.getPublic("site-signing"); * PublicKey pub = reloaded.getPublic("site-signing");
* }</pre> * }</pre>
*/ */
public final class KeyringStore { public final class KeyringStore { // NOPMD
private static final String MAGIC_HEADER = "# KeyringStore v1"; private static final String MAGIC_HEADER = "# KeyringStore v1";
private static final String ENTRY_MARKER = "@entry"; private static final String ENTRY_MARKER = "@entry";
private static final String PREFIX_SPEC = "s."; // marks spec payload keys 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<String, Record> byAlias = new LinkedHashMap<>(); private final Map<String, Record> byAlias = new LinkedHashMap<>();
/** /**
@@ -163,7 +169,7 @@ public final class KeyringStore {
* @throws IllegalArgumentException if any argument is invalid * @throws IllegalArgumentException if any argument is invalid
*/ */
public void putPublic(String alias, String algorithmId, AlgorithmKeySpec importSpec) { 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 * @throws IllegalArgumentException if any argument is invalid
*/ */
public void putPrivate(String alias, String algorithmId, AlgorithmKeySpec importSpec) { 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 * @return true if an entry exists for the alias, false otherwise
*/ */
public boolean contains(String alias) { 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 * @return a new list of aliases; the returned list is mutable but independent
*/ */
public List<String> aliases() { public List<String> aliases() {
return new ArrayList<>(byAlias.keySet()); List<String> 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 * @throws IllegalArgumentException if alias is missing or not a public key
*/ */
public PublicWithId getPublicWithId(String alias) throws GeneralSecurityException { 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); AlgorithmKeySpec spec = unmarshalSpec(r.specClass, r.specPayload);
PublicKey key = CryptoAlgorithms.publicKey(r.algorithm, spec); PublicKey key = CryptoAlgorithms.publicKey(r.algorithm, spec);
return new PublicWithId(r.algorithm, key); 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 * @throws IllegalArgumentException if alias is missing or not a private key
*/ */
public PrivateWithId getPrivateWithId(String alias) throws GeneralSecurityException { 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); AlgorithmKeySpec spec = unmarshalSpec(r.specClass, r.specPayload);
PrivateKey key = CryptoAlgorithms.privateKey(r.algorithm, spec); PrivateKey key = CryptoAlgorithms.privateKey(r.algorithm, spec);
return new PrivateWithId(r.algorithm, key); return new PrivateWithId(r.algorithm, key);
@@ -319,7 +335,7 @@ public final class KeyringStore {
* a public key * a public key
*/ */
public PublicKey getPublic(String alias) throws GeneralSecurityException { 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); AlgorithmKeySpec spec = unmarshalSpec(r.specClass, r.specPayload);
return CryptoAlgorithms.publicKey(r.algorithm, spec); return CryptoAlgorithms.publicKey(r.algorithm, spec);
} }
@@ -335,11 +351,44 @@ public final class KeyringStore {
* a private key * a private key
*/ */
public PrivateKey getPrivate(String alias) throws GeneralSecurityException { 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); AlgorithmKeySpec spec = unmarshalSpec(r.specClass, r.specPayload);
return CryptoAlgorithms.privateKey(r.algorithm, spec); 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. * Resolves the secret key bound to the alias.
* *

View File

@@ -19,13 +19,6 @@
<attribute name="test" value="true"/> <attribute name="test" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/resources">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-21/"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-21/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/> <classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/> <classpathentry kind="output" path="bin/default"/>

View File

@@ -3,7 +3,7 @@ plugins {
id 'com.palantir.git-version' id 'com.palantir.git-version'
} }
group 'org.egothor' group='org.egothor'
dependencies { dependencies {
implementation 'org.apache.commons:commons-text' implementation 'org.apache.commons:commons-text'