From 6ecca14e6ec7e512d7aca15c99c52b11effff8ae Mon Sep 17 00:00:00 2001 From: James Rosewell Date: Wed, 2 Sep 2026 09:08:00 +0100 Subject: [PATCH] Finish the match key rename in the 51Did payload constants The earlier rename of the stable, comparable part of a 51Did to "match key" was only half done. Two payload constants still carried the old hash name even though their own documentation already called the field a match key, so the code read one way and the names read another. MATCH_KEY_OFFSET and MATCH_KEY_LENGTH are now the real constants and keep their values of 5 and 32. HEADER_LENGTH and PAYLOAD_LENGTH keep their own names and are worked out from the new constants. HASH_OFFSET and HASH_LENGTH stay as deprecated aliases of the same two values, worded the same way as the getHash alias already in the file, so code written against the earlier names keeps compiling. All 23 uses of the old names move to the new ones, across the 51Did package, its tests and the 51Did developer example, and the package README now describes the naming. A test asserts the two aliases still read the same values as the constants they point at. Nothing to do with SHA-256 hashing itself, or with the unrelated Device Detection Hash classes, is renamed. --- .../developerexamples/fodid/Main.java | 4 +-- .../developerexamples/fodid/ExampleTests.java | 4 +-- pipeline.did/README.md | 6 ++++ .../java/fiftyone/pipeline/did/DidClient.java | 2 +- .../java/fiftyone/pipeline/did/FodId.java | 35 +++++++++++++++---- .../pipeline/did/FodIdTestFactory.java | 6 ++-- .../fiftyone/pipeline/did/FodIdTests.java | 27 ++++++++++---- 7 files changed, 63 insertions(+), 21 deletions(-) diff --git a/pipeline.developer-examples/pipeline.developer-examples.fodid/src/main/java/pipeline/developerexamples/fodid/Main.java b/pipeline.developer-examples/pipeline.developer-examples.fodid/src/main/java/pipeline/developerexamples/fodid/Main.java index 7e82805eb..ada0f49d9 100644 --- a/pipeline.developer-examples/pipeline.developer-examples.fodid/src/main/java/pipeline/developerexamples/fodid/Main.java +++ b/pipeline.developer-examples/pipeline.developer-examples.fodid/src/main/java/pipeline/developerexamples/fodid/Main.java @@ -109,8 +109,8 @@ private byte[] samplePayload() { payload[FodId.LICENSE_ID_OFFSET + 1] = 0x56; payload[FodId.LICENSE_ID_OFFSET + 2] = 0x34; payload[FodId.LICENSE_ID_OFFSET + 3] = 0x12; - for (int i = 0; i < FodId.HASH_LENGTH; i++) { - payload[FodId.HASH_OFFSET + i] = (byte) (0x20 + i); + for (int i = 0; i < FodId.MATCH_KEY_LENGTH; i++) { + payload[FodId.MATCH_KEY_OFFSET + i] = (byte) (0x20 + i); } return payload; } diff --git a/pipeline.developer-examples/pipeline.developer-examples.fodid/src/test/java/pipeline/developerexamples/fodid/ExampleTests.java b/pipeline.developer-examples/pipeline.developer-examples.fodid/src/test/java/pipeline/developerexamples/fodid/ExampleTests.java index 7f37bc31e..f5f87e5d9 100644 --- a/pipeline.developer-examples/pipeline.developer-examples.fodid/src/test/java/pipeline/developerexamples/fodid/ExampleTests.java +++ b/pipeline.developer-examples/pipeline.developer-examples.fodid/src/test/java/pipeline/developerexamples/fodid/ExampleTests.java @@ -249,8 +249,8 @@ private static byte[] samplePayload() { payload[FodId.LICENSE_ID_OFFSET + 1] = 0x56; payload[FodId.LICENSE_ID_OFFSET + 2] = 0x34; payload[FodId.LICENSE_ID_OFFSET + 3] = 0x12; - for (int i = 0; i < FodId.HASH_LENGTH; i++) { - payload[FodId.HASH_OFFSET + i] = (byte) (0x20 + i); + for (int i = 0; i < FodId.MATCH_KEY_LENGTH; i++) { + payload[FodId.MATCH_KEY_OFFSET + i] = (byte) (0x20 + i); } return payload; } diff --git a/pipeline.did/README.md b/pipeline.did/README.md index 21b9f18f1..9fc74c88f 100644 --- a/pipeline.did/README.md +++ b/pipeline.did/README.md @@ -198,6 +198,12 @@ Use `getMatchKey()` as the cache / dedup key. `getHash()` remains as a deprecated alias of `getMatchKey()`, returning the same bytes, and will be removed in a future release. +The payload constants follow the same naming. `MATCH_KEY_OFFSET` and +`MATCH_KEY_LENGTH` give the position and the size of the match key inside the +payload, and `HASH_OFFSET` and `HASH_LENGTH` remain as deprecated aliases of +the same two values so that code written against the earlier names keeps +compiling. The aliases will be removed in a future release. + ## Verifying on your server `DidClient` handles every manipulation of a 51Did a server needs against the diff --git a/pipeline.did/src/main/java/fiftyone/pipeline/did/DidClient.java b/pipeline.did/src/main/java/fiftyone/pipeline/did/DidClient.java index 03dfc3095..d542fb77d 100644 --- a/pipeline.did/src/main/java/fiftyone/pipeline/did/DidClient.java +++ b/pipeline.did/src/main/java/fiftyone/pipeline/did/DidClient.java @@ -487,7 +487,7 @@ public SignatureCheck verifySignatureDetailed(FodId fodId) } boolean isRandom = fodId.getType() == IdType.RANDOM; int baseLength = FodId.HEADER_LENGTH - + (isRandom ? FodId.GUID_LENGTH : FodId.HASH_LENGTH); + + (isRandom ? FodId.GUID_LENGTH : FodId.MATCH_KEY_LENGTH); if (fodId.getPayload().length < baseLength) { return SignatureCheck.MALFORMED_PAYLOAD; } diff --git a/pipeline.did/src/main/java/fiftyone/pipeline/did/FodId.java b/pipeline.did/src/main/java/fiftyone/pipeline/did/FodId.java index 5445809be..996095347 100644 --- a/pipeline.did/src/main/java/fiftyone/pipeline/did/FodId.java +++ b/pipeline.did/src/main/java/fiftyone/pipeline/did/FodId.java @@ -97,16 +97,38 @@ public final class FodId { public static final int LICENSE_ID_LENGTH = 4; /** Byte offset of the match key field within the payload. */ - public static final int HASH_OFFSET = 5; + public static final int MATCH_KEY_OFFSET = 5; /** Byte length of the match key field (SHA-256). */ - public static final int HASH_LENGTH = 32; + public static final int MATCH_KEY_LENGTH = 32; + + /** + * Deprecated alias for {@link #MATCH_KEY_OFFSET}. The stable, comparable + * part of a 51Did is now called the match key, mirroring the Model Terms + * for Marketing vocabulary. This alias will be removed in a future + * release. + * + * @deprecated renamed to {@link #MATCH_KEY_OFFSET} + */ + @Deprecated + public static final int HASH_OFFSET = MATCH_KEY_OFFSET; + + /** + * Deprecated alias for {@link #MATCH_KEY_LENGTH}. The stable, comparable + * part of a 51Did is now called the match key, mirroring the Model Terms + * for Marketing vocabulary. This alias will be removed in a future + * release. + * + * @deprecated renamed to {@link #MATCH_KEY_LENGTH} + */ + @Deprecated + public static final int HASH_LENGTH = MATCH_KEY_LENGTH; /** * Byte length of the payload header (Flags + License Id) common to every * identifier type. */ - public static final int HEADER_LENGTH = HASH_OFFSET; + public static final int HEADER_LENGTH = MATCH_KEY_OFFSET; /** Byte length of the GUID match key carried by Random identifiers. */ public static final int GUID_LENGTH = 16; @@ -122,7 +144,8 @@ public final class FodId { * (Flags + License Id + match key). Random payloads are shorter - see * {@link #RANDOM_PAYLOAD_LENGTH}. */ - public static final int PAYLOAD_LENGTH = HASH_OFFSET + HASH_LENGTH; + public static final int PAYLOAD_LENGTH = + MATCH_KEY_OFFSET + MATCH_KEY_LENGTH; /** * The origin the envelope's date counts from, 2020-01-01T00:00:00Z, as @@ -227,7 +250,7 @@ private static FodIdParseResult read(Owid owid) { matchKeyLength = payload.length - HEADER_LENGTH; break; default: - matchKeyLength = HASH_LENGTH; + matchKeyLength = MATCH_KEY_LENGTH; break; } if (payload.length < HEADER_LENGTH + matchKeyLength) { @@ -245,7 +268,7 @@ private static FodIdParseResult read(Owid owid) { // gets back from getMatchKey() can never reach the envelope's own // bytes. byte[] matchKey = Arrays.copyOfRange( - payload, HASH_OFFSET, HASH_OFFSET + matchKeyLength); + payload, MATCH_KEY_OFFSET, MATCH_KEY_OFFSET + matchKeyLength); return FodIdParseResult.parsed( new FodId(owid, flags, licenseId, matchKey)); } diff --git a/pipeline.did/src/test/java/fiftyone/pipeline/did/FodIdTestFactory.java b/pipeline.did/src/test/java/fiftyone/pipeline/did/FodIdTestFactory.java index e92f6e77e..083c9f26f 100644 --- a/pipeline.did/src/test/java/fiftyone/pipeline/did/FodIdTestFactory.java +++ b/pipeline.did/src/test/java/fiftyone/pipeline/did/FodIdTestFactory.java @@ -74,7 +74,7 @@ final class FodIdTestFactory { } private static byte[] canonicalMatchKey() { - byte[] matchKey = new byte[FodId.HASH_LENGTH]; + byte[] matchKey = new byte[FodId.MATCH_KEY_LENGTH]; for (int i = 0; i < matchKey.length; i++) { matchKey[i] = (byte) (0x20 + i); } @@ -87,7 +87,7 @@ static byte[] canonicalPayload() { writeCanonicalLicenseId(payload); System.arraycopy( CANONICAL_MATCH_KEY, 0, payload, - FodId.HASH_OFFSET, FodId.HASH_LENGTH); + FodId.MATCH_KEY_OFFSET, FodId.MATCH_KEY_LENGTH); return payload; } @@ -96,7 +96,7 @@ static byte[] canonicalRandomPayload() { payload[FodId.FLAGS_OFFSET] = (byte) ((1 << 6) | 0b001); writeCanonicalLicenseId(payload); for (int i = 0; i < FodId.GUID_LENGTH; i++) { - payload[FodId.HASH_OFFSET + i] = (byte) (0x40 + i); + payload[FodId.MATCH_KEY_OFFSET + i] = (byte) (0x40 + i); } return payload; } diff --git a/pipeline.did/src/test/java/fiftyone/pipeline/did/FodIdTests.java b/pipeline.did/src/test/java/fiftyone/pipeline/did/FodIdTests.java index 9afdce4c9..ff207546a 100644 --- a/pipeline.did/src/test/java/fiftyone/pipeline/did/FodIdTests.java +++ b/pipeline.did/src/test/java/fiftyone/pipeline/did/FodIdTests.java @@ -66,9 +66,12 @@ public void init() throws OwidException { @Test public void constants_AreInternallyConsistent() { - assertEquals(FodId.PAYLOAD_LENGTH, FodId.HASH_OFFSET + FodId.HASH_LENGTH); - assertEquals(FodId.HASH_OFFSET, FodId.LICENSE_ID_OFFSET + FodId.LICENSE_ID_LENGTH); - assertEquals(FodId.RANDOM_PAYLOAD_LENGTH, FodId.HASH_OFFSET + FodId.GUID_LENGTH); + assertEquals(FodId.PAYLOAD_LENGTH, + FodId.MATCH_KEY_OFFSET + FodId.MATCH_KEY_LENGTH); + assertEquals(FodId.MATCH_KEY_OFFSET, + FodId.LICENSE_ID_OFFSET + FodId.LICENSE_ID_LENGTH); + assertEquals(FodId.RANDOM_PAYLOAD_LENGTH, + FodId.MATCH_KEY_OFFSET + FodId.GUID_LENGTH); } @Test @@ -190,11 +193,11 @@ public void matchKey_IsDefensiveCopy() throws Exception { byte[] matchKey = fodId.getMatchKey(); matchKey[0] = 0x00; - matchKey[FodId.HASH_LENGTH - 1] = 0x00; + matchKey[FodId.MATCH_KEY_LENGTH - 1] = 0x00; // Neither the underlying payload nor a fresh getMatchKey() is affected. assertEquals( - CANONICAL_MATCH_KEY[0], fodId.getPayload()[FodId.HASH_OFFSET]); + CANONICAL_MATCH_KEY[0], fodId.getPayload()[FodId.MATCH_KEY_OFFSET]); assertArrayEquals(CANONICAL_MATCH_KEY, fodId.getMatchKey()); } @@ -209,6 +212,16 @@ public void getHash_DeprecatedAlias_ReturnsMatchKey() throws Exception { assertArrayEquals(CANONICAL_MATCH_KEY, fodId.getHash()); } + @Test + @SuppressWarnings("deprecation") + public void hashConstants_DeprecatedAliases_MatchNewNames() { + // HASH_OFFSET and HASH_LENGTH stay as deprecated aliases so that + // callers written against the earlier names keep compiling and read + // the same values as the match key constants they now point at. + assertEquals(FodId.MATCH_KEY_OFFSET, FodId.HASH_OFFSET); + assertEquals(FodId.MATCH_KEY_LENGTH, FodId.HASH_LENGTH); + } + @Test public void constructor_PayloadOneByteShort_Throws() throws Exception { // 36 bytes - one short of the minimum 37 (flags 0 -> Probabilistic). @@ -251,7 +264,7 @@ public void constructor_PayloadLargerThanSpec_UsesFirst37Bytes() throws Exceptio assertEquals(CANONICAL_FLAGS, fodId.getFlags()); assertEquals(CANONICAL_LICENSE_ID, fodId.getLicenseId()); assertArrayEquals(CANONICAL_MATCH_KEY, fodId.getMatchKey()); - assertEquals(FodId.HASH_LENGTH, fodId.getMatchKey().length); + assertEquals(FodId.MATCH_KEY_LENGTH, fodId.getMatchKey().length); } @Test @@ -366,7 +379,7 @@ public void constructor_HashedEmailPayloadOneByteShort_Throws() throws Exception @Test public void constructor_ReservedHeaderOnly_Parses() throws Exception { - byte[] payload = new byte[FodId.HASH_OFFSET]; + byte[] payload = new byte[FodId.MATCH_KEY_OFFSET]; payload[FodId.FLAGS_OFFSET] = (byte) 0b1100_0000; FodId fodId = FodId.fromBase64(factory.signedOwidBase64(payload));