mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 03:58:21 +00:00
8367008: Algorithm identifiers for HmacSHA* should always have NULL as params
Reviewed-by: weijun
This commit is contained in:
parent
d8ebe38759
commit
4377e7c9e8
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -127,10 +127,35 @@ public class AlgorithmId implements Serializable, DerEncoder {
|
||||
public AlgorithmId(ObjectIdentifier oid, DerValue params)
|
||||
throws IOException {
|
||||
this.algid = oid;
|
||||
if (params != null) {
|
||||
encodedParams = params.toByteArray();
|
||||
decodeParams();
|
||||
|
||||
if (params == null) {
|
||||
this.encodedParams = null;
|
||||
this.algParams = null;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the parameters field explicitly contains an ASN.1 NULL, treat it as
|
||||
* "no parameters" rather than storing a literal NULL encoding.
|
||||
*
|
||||
* This canonicalization ensures consistent encoding/decoding behavior:
|
||||
* - Algorithms that omit parameters and those that encode explicit NULL
|
||||
* are treated equivalently (encodedParams == null).
|
||||
*/
|
||||
if (params.tag == DerValue.tag_Null) {
|
||||
if (params.length() != 0) {
|
||||
throw new IOException("Invalid ASN.1 NULL in AlgorithmId parameters: " +
|
||||
"non-zero length");
|
||||
}
|
||||
// Canonicalize to "no parameters" representation for consistency
|
||||
this.encodedParams = null;
|
||||
this.algParams = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Normal case: non-NULL params -> store and decode
|
||||
this.encodedParams = params.toByteArray();
|
||||
decodeParams();
|
||||
}
|
||||
|
||||
protected void decodeParams() throws IOException {
|
||||
@ -163,38 +188,10 @@ public class AlgorithmId implements Serializable, DerEncoder {
|
||||
bytes.putOID(algid);
|
||||
|
||||
if (encodedParams == null) {
|
||||
// MessageDigest algorithms usually have a NULL parameters even
|
||||
// if most RFCs suggested absent.
|
||||
// RSA key and signature algorithms requires the NULL parameters
|
||||
// to be present, see A.1 and A.2.4 of RFC 8017.
|
||||
if (algid.equals(RSAEncryption_oid)
|
||||
|| algid.equals(MD2_oid)
|
||||
|| algid.equals(MD5_oid)
|
||||
|| algid.equals(SHA_oid)
|
||||
|| algid.equals(SHA224_oid)
|
||||
|| algid.equals(SHA256_oid)
|
||||
|| algid.equals(SHA384_oid)
|
||||
|| algid.equals(SHA512_oid)
|
||||
|| algid.equals(SHA512_224_oid)
|
||||
|| algid.equals(SHA512_256_oid)
|
||||
|| algid.equals(SHA3_224_oid)
|
||||
|| algid.equals(SHA3_256_oid)
|
||||
|| algid.equals(SHA3_384_oid)
|
||||
|| algid.equals(SHA3_512_oid)
|
||||
|| algid.equals(SHA1withRSA_oid)
|
||||
|| algid.equals(SHA224withRSA_oid)
|
||||
|| algid.equals(SHA256withRSA_oid)
|
||||
|| algid.equals(SHA384withRSA_oid)
|
||||
|| algid.equals(SHA512withRSA_oid)
|
||||
|| algid.equals(SHA512$224withRSA_oid)
|
||||
|| algid.equals(SHA512$256withRSA_oid)
|
||||
|| algid.equals(MD2withRSA_oid)
|
||||
|| algid.equals(MD5withRSA_oid)
|
||||
|| algid.equals(SHA3_224withRSA_oid)
|
||||
|| algid.equals(SHA3_256withRSA_oid)
|
||||
|| algid.equals(SHA3_384withRSA_oid)
|
||||
|| algid.equals(SHA3_512withRSA_oid)) {
|
||||
if (OIDS_REQUIRING_NULL.contains(algid.toString())) {
|
||||
bytes.putNull();
|
||||
} else {
|
||||
// Parameters omitted
|
||||
}
|
||||
} else {
|
||||
bytes.writeBytes(encodedParams);
|
||||
@ -646,30 +643,54 @@ public class AlgorithmId implements Serializable, DerEncoder {
|
||||
public static final ObjectIdentifier MGF1_oid =
|
||||
ObjectIdentifier.of(KnownOIDs.MGF1);
|
||||
|
||||
public static final ObjectIdentifier SHA1withRSA_oid =
|
||||
ObjectIdentifier.of(KnownOIDs.SHA1withRSA);
|
||||
public static final ObjectIdentifier SHA224withRSA_oid =
|
||||
ObjectIdentifier.of(KnownOIDs.SHA224withRSA);
|
||||
public static final ObjectIdentifier SHA256withRSA_oid =
|
||||
ObjectIdentifier.of(KnownOIDs.SHA256withRSA);
|
||||
public static final ObjectIdentifier SHA384withRSA_oid =
|
||||
ObjectIdentifier.of(KnownOIDs.SHA384withRSA);
|
||||
public static final ObjectIdentifier SHA512withRSA_oid =
|
||||
ObjectIdentifier.of(KnownOIDs.SHA512withRSA);
|
||||
public static final ObjectIdentifier SHA512$224withRSA_oid =
|
||||
ObjectIdentifier.of(KnownOIDs.SHA512$224withRSA);
|
||||
public static final ObjectIdentifier SHA512$256withRSA_oid =
|
||||
ObjectIdentifier.of(KnownOIDs.SHA512$256withRSA);
|
||||
public static final ObjectIdentifier MD2withRSA_oid =
|
||||
ObjectIdentifier.of(KnownOIDs.MD2withRSA);
|
||||
public static final ObjectIdentifier MD5withRSA_oid =
|
||||
ObjectIdentifier.of(KnownOIDs.MD5withRSA);
|
||||
public static final ObjectIdentifier SHA3_224withRSA_oid =
|
||||
ObjectIdentifier.of(KnownOIDs.SHA3_224withRSA);
|
||||
public static final ObjectIdentifier SHA3_256withRSA_oid =
|
||||
ObjectIdentifier.of(KnownOIDs.SHA3_256withRSA);
|
||||
public static final ObjectIdentifier SHA3_384withRSA_oid =
|
||||
ObjectIdentifier.of(KnownOIDs.SHA3_384withRSA);
|
||||
public static final ObjectIdentifier SHA3_512withRSA_oid =
|
||||
ObjectIdentifier.of(KnownOIDs.SHA3_512withRSA);
|
||||
/* Set of OIDs that must explicitly encode a NULL parameter in AlgorithmIdentifier.
|
||||
* References:
|
||||
- RFC 8017 (PKCS #1) §A.1, §A.2.4: RSA key and signature algorithms
|
||||
- RFC 9879 (HMAC) §4: HMAC algorithm identifiers
|
||||
- RFC 9688 (HMAC with SHA-3) §4.3: HMAC-SHA3 algorithms MUST omit parameters
|
||||
*/
|
||||
private static final Set<String> OIDS_REQUIRING_NULL = Set.of(
|
||||
// MessageDigest algorithms usually have a NULL parameters even
|
||||
// if most RFCs suggested absent.
|
||||
KnownOIDs.MD2.value(),
|
||||
KnownOIDs.MD5.value(),
|
||||
KnownOIDs.SHA_1.value(),
|
||||
KnownOIDs.SHA_224.value(),
|
||||
KnownOIDs.SHA_256.value(),
|
||||
KnownOIDs.SHA_384.value(),
|
||||
KnownOIDs.SHA_512.value(),
|
||||
KnownOIDs.SHA_512$224.value(),
|
||||
KnownOIDs.SHA_512$256.value(),
|
||||
KnownOIDs.SHA3_224.value(),
|
||||
KnownOIDs.SHA3_256.value(),
|
||||
KnownOIDs.SHA3_384.value(),
|
||||
KnownOIDs.SHA3_512.value(),
|
||||
|
||||
//--- RSA key and signature algorithms (RFC 8017 §A.1, §A.2.4)
|
||||
KnownOIDs.RSA.value(),
|
||||
KnownOIDs.SHA1withRSA.value(),
|
||||
KnownOIDs.SHA224withRSA.value(),
|
||||
KnownOIDs.SHA256withRSA.value(),
|
||||
KnownOIDs.SHA384withRSA.value(),
|
||||
KnownOIDs.SHA512withRSA.value(),
|
||||
KnownOIDs.SHA512$224withRSA.value(),
|
||||
KnownOIDs.SHA512$256withRSA.value(),
|
||||
KnownOIDs.MD2withRSA.value(),
|
||||
KnownOIDs.MD5withRSA.value(),
|
||||
KnownOIDs.SHA3_224withRSA.value(),
|
||||
KnownOIDs.SHA3_256withRSA.value(),
|
||||
KnownOIDs.SHA3_384withRSA.value(),
|
||||
KnownOIDs.SHA3_512withRSA.value(),
|
||||
|
||||
// HMACs per RFC 9879 (Section 4): these require explicit NULL parameters
|
||||
// Note: HMAC-SHA3 algorithms (RFC 9688 §4.3) MUST omit parameters,
|
||||
// so they are intentionally excluded from this list.
|
||||
KnownOIDs.HmacSHA1.value(),
|
||||
KnownOIDs.HmacSHA224.value(),
|
||||
KnownOIDs.HmacSHA256.value(),
|
||||
KnownOIDs.HmacSHA384.value(),
|
||||
KnownOIDs.HmacSHA512.value(),
|
||||
KnownOIDs.HmacSHA512$224.value(),
|
||||
KnownOIDs.HmacSHA512$256.value()
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,16 +24,19 @@
|
||||
/*
|
||||
* @test
|
||||
* @author Gary Ellison
|
||||
* @bug 4170635 8258247
|
||||
* @bug 4170635 8258247 8367008
|
||||
* @library /test/lib
|
||||
* @summary Verify equals()/hashCode() contract honored
|
||||
* @modules java.base/sun.security.x509 java.base/sun.security.util
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.io.IOException;
|
||||
import java.security.AlgorithmParameters;
|
||||
import java.security.spec.MGF1ParameterSpec;
|
||||
import java.security.spec.PSSParameterSpec;
|
||||
|
||||
import jdk.test.lib.Asserts;
|
||||
|
||||
import sun.security.util.DerValue;
|
||||
import sun.security.x509.*;
|
||||
|
||||
@ -97,5 +100,20 @@ public class AlgorithmIdEqualsHashCode {
|
||||
} else {
|
||||
System.out.println("PASSED equals() test");
|
||||
}
|
||||
|
||||
// Construct an AlgorithmId with explicit DER NULL parameters
|
||||
DerValue explicitNullParams = new DerValue(DerValue.tag_Null, new byte[0]);
|
||||
AlgorithmId aiNullParams = new AlgorithmId(AlgorithmId.SHA256_oid,
|
||||
explicitNullParams);
|
||||
// The constructor should canonicalize this to "no parameters"
|
||||
Asserts.assertTrue(aiNullParams.getEncodedParams() == null);
|
||||
AlgorithmId aiNormal = AlgorithmId.get("SHA-256");
|
||||
Asserts.assertEquals(aiNullParams, aiNormal);
|
||||
Asserts.assertEquals(aiNullParams.hashCode(), aiNormal.hashCode());
|
||||
|
||||
// Test invalid ASN.1 NULL (non-zero length)
|
||||
DerValue invalidNull = new DerValue(DerValue.tag_Null, new byte[]{0x00});
|
||||
Asserts.assertThrows(IOException.class,
|
||||
() -> new AlgorithmId(AlgorithmId.SHA256_oid, invalidNull));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -67,6 +67,13 @@ public class NullParams {
|
||||
test("SHA3-256withRSA", true);
|
||||
test("SHA3-384withRSA", true);
|
||||
test("SHA3-512withRSA", true);
|
||||
test("HmacSHA1", true);
|
||||
test("HmacSHA224", true);
|
||||
test("HmacSHA256", true);
|
||||
test("HmacSHA384", true);
|
||||
test("HmacSHA512", true);
|
||||
test("HmacSHA512/224", true);
|
||||
test("HmacSHA512/256", true);
|
||||
|
||||
// Full old list: must be absent
|
||||
test("SHA1withECDSA", false);
|
||||
@ -83,7 +90,6 @@ public class NullParams {
|
||||
// Others
|
||||
test("DSA", false);
|
||||
test("SHA1withDSA", false);
|
||||
test("HmacSHA1", false);
|
||||
|
||||
if (failed) {
|
||||
throw new RuntimeException("At least one failed");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user