/
wstartsev
/
jdk
Обзор
Документация
Войти
/
wstartsev
/
jdk
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/java.base/share/classes/sun/security/util/PBKDF2Parameters.java
214 строк
7 KB
Mark Powers
8371156: PBKDF2 default values should not be DER encoded
17 ноя 2025, 17:59
17 ноя 2025, 17:59
52ffe8a
Код
Авторство
О чём код?
/* * Copyright (c) 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.security.util; import java.io.IOException; import sun.security.x509.AlgorithmId; /** * This class implements the parameter set used with password-based * key derivation function 2 (PBKDF2), which is defined in PKCS#5 as follows: * * <pre> * * PBKDF2Algorithms ALGORITHM-IDENTIFIER ::= * { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ...} * * id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} * * PBKDF2-params ::= SEQUENCE { * salt CHOICE { * specified OCTET STRING, * otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}} * }, * iterationCount INTEGER (1..MAX), * keyLength INTEGER (1..MAX) OPTIONAL, * prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 * } * * PBKDF2-SaltSources ALGORITHM-IDENTIFIER ::= { ... } * * PBKDF2-PRFs ALGORITHM-IDENTIFIER ::= { * {NULL IDENTIFIED BY id-hmacWithSHA1} | * {NULL IDENTIFIED BY id-hmacWithSHA224} | * {NULL IDENTIFIED BY id-hmacWithSHA256} | * {NULL IDENTIFIED BY id-hmacWithSHA384} | * {NULL IDENTIFIED BY id-hmacWithSHA512}, ... } * * algid-hmacWithSHA1 AlgorithmIdentifier {{PBKDF2-PRFs}} ::= * {algorithm id-hmacWithSHA1, parameters NULL : NULL} * * id-hmacWithSHA1 OBJECT IDENTIFIER ::= {digestAlgorithm 7} * * For more information, see * <a href="https://tools.ietf.org/html/rfc8018">RFC 8018: * PKCS #5: Password-Based Cryptography Specification</a>. * * </pre> */ public final class PBKDF2Parameters { private final byte[] salt; private final int iterationCount; // keyLength in bits, or -1 if not present private final int keyLength; private final String prfAlgo; /** * Initialize PBKDF2Parameters from a DER encoded * parameter block. * * @param pBKDF2_params the DER encoding of the parameter block * * @throws IOException for parsing errors in the input stream */ public PBKDF2Parameters(DerValue pBKDF2_params) throws IOException { if (pBKDF2_params.tag != DerValue.tag_Sequence) { throw new IOException("PBKDF2 parameter parsing error: " + "not an ASN.1 SEQUENCE tag"); } DerValue specified = pBKDF2_params.data.getDerValue(); // the 'specified' ASN.1 CHOICE for 'salt' is supported if (specified.tag == DerValue.tag_OctetString) { salt = specified.getOctetString(); } else { // the 'otherSource' ASN.1 CHOICE for 'salt' is not supported throw new IOException("PBKDF2 parameter parsing error: " + "not an ASN.1 OCTET STRING tag"); } iterationCount = pBKDF2_params.data.getInteger(); // keyLength INTEGER (1..MAX) OPTIONAL, var ksDer = pBKDF2_params.data.getOptional(DerValue.tag_Integer); if (ksDer.isPresent()) { keyLength = ksDer.get().getInteger() * 8; // keyLength (in bits) } else { keyLength = -1; } // prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 var prfDer = pBKDF2_params.data.getOptional(DerValue.tag_Sequence); if (prfDer.isPresent()) { DerValue prf = prfDer.get(); // the pseudorandom function (default is HmacSHA1) ObjectIdentifier kdfAlgo_OID = prf.data.getOID(); KnownOIDs o = KnownOIDs.findMatch(kdfAlgo_OID.toString()); if (o == null || (!o.stdName().equals("HmacSHA1") && !o.stdName().equals("HmacSHA224") && !o.stdName().equals("HmacSHA256") && !o.stdName().equals("HmacSHA384") && !o.stdName().equals("HmacSHA512") && !o.stdName().equals("HmacSHA512/224") && !o.stdName().equals("HmacSHA512/256"))) { throw new IOException("PBKDF2 parameter parsing error: " + "expecting the object identifier for a HmacSHA " + "pseudorandom function"); } prfAlgo = o.stdName(); prf.data.getOptional(DerValue.tag_Null); prf.data.atEnd(); } else { prfAlgo = "HmacSHA1"; } } public static byte[] encode(byte[] salt, int iterationCount, int keyLength, String kdfHmac) { ObjectIdentifier prf = ObjectIdentifier.of(KnownOIDs.findMatch(kdfHmac)); return PBKDF2Parameters.encode(salt, iterationCount, keyLength, prf); } /* * Encode PBKDF2 parameters from components. * The outer algorithm ID is also encoded in addition to the parameters. */ public static byte[] encode(byte[] salt, int iterationCount, int keyLength, ObjectIdentifier prf) { assert keyLength != -1; DerOutputStream out = new DerOutputStream(); DerOutputStream tmp0 = new DerOutputStream(); tmp0.putOctetString(salt); tmp0.putInteger(iterationCount); tmp0.putInteger(keyLength); // prf AlgorithmIdentifier {{PBKDF2-PRFs}} // HmacSHA1 is the default and must not be encoded. if (!prf.equals(ObjectIdentifier.of(KnownOIDs.HmacSHA1))) { tmp0.write(new AlgorithmId(prf)); } // id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} out.putOID(ObjectIdentifier.of(KnownOIDs.PBKDF2)); out.write(DerValue.tag_Sequence, tmp0); return new DerOutputStream().write(DerValue.tag_Sequence, out) .toByteArray(); } /** * Returns the salt. * * @return the salt */ public byte[] getSalt() { return this.salt; } /** * Returns the iteration count. * * @return the iteration count */ public int getIterationCount() { return this.iterationCount; } /** * Returns size of key generated by PBKDF2, or -1 if not found/set. * * @return size of key generated by PBKDF2, or -1 if not found/set */ public int getKeyLength() { return this.keyLength; } /** * Returns name of Hmac. * * @return name of Hmac */ public String getPrfAlgo() { return this.prfAlgo; } }