/* * Copyright (c) 2013, 2020, 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 java.security; import java.io.IOException; import java.math.BigInteger; import java.util.Arrays; import java.util.regex.Pattern; import sun.security.util.*; /** * An attribute associated with a PKCS12 keystore entry. * The attribute name is an ASN.1 Object Identifier and the attribute * value is a set of ASN.1 types. * * @since 1.8 */ public final class PKCS12Attribute implements KeyStore.Entry.Attribute { private static final Pattern COLON_SEPARATED_HEX_PAIRS = Pattern.compile("^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2})+$"); private String name; private String value; private byte[] encoded; private int hashValue = -1; /** * Constructs a PKCS12 attribute from its name and value. * The name is an ASN.1 Object Identifier represented as a list of * dot-separated integers. * A string value is represented as the string itself. * A binary value is represented as a string of colon-separated * pairs of hexadecimal digits. * Multi-valued attributes are represented as a comma-separated * list of values, enclosed in square brackets. See * {@link Arrays#toString(java.lang.Object[])}. *
* A string value will be DER-encoded as an ASN.1 UTF8String and a * binary value will be DER-encoded as an ASN.1 Octet String. * * @param name the attribute's identifier * @param value the attribute's value * * @exception NullPointerException if {@code name} or {@code value} * is {@code null} * @exception IllegalArgumentException if {@code name} or * {@code value} is incorrectly formatted */ public PKCS12Attribute(String name, String value) { if (name == null || value == null) { throw new NullPointerException(); } // Validate name ObjectIdentifier type; try { type = new ObjectIdentifier(name); } catch (IOException e) { throw new IllegalArgumentException("Incorrect format: name", e); } this.name = name; // Validate value int length = value.length(); String[] values; if (value.charAt(0) == '[' && value.charAt(length - 1) == ']') { values = value.substring(1, length - 1).split(", "); } else { values = new String[]{ value }; } this.value = value; try { this.encoded = encode(type, values); } catch (IOException e) { throw new IllegalArgumentException("Incorrect format: value", e); } } /** * Constructs a PKCS12 attribute from its ASN.1 DER encoding. * The DER encoding is specified by the following ASN.1 definition: *
* * Attribute ::= SEQUENCE { * type AttributeType, * values SET OF AttributeValue * } * AttributeType ::= OBJECT IDENTIFIER * AttributeValue ::= ANY defined by type * ** * @param encoded the attribute's ASN.1 DER encoding. It is cloned * to prevent subsequent modificaion. * * @exception NullPointerException if {@code encoded} is * {@code null} * @exception IllegalArgumentException if {@code encoded} is * incorrectly formatted */ public PKCS12Attribute(byte[] encoded) { if (encoded == null) { throw new NullPointerException(); } this.encoded = encoded.clone(); try { parse(encoded); } catch (IOException e) { throw new IllegalArgumentException("Incorrect format: encoded", e); } } /** * Returns the attribute's ASN.1 Object Identifier represented as a * list of dot-separated integers. * * @return the attribute's identifier */ @Override public String getName() { return name; } /** * Returns the attribute's ASN.1 DER-encoded value as a string. * An ASN.1 DER-encoded value is returned in one of the following * {@code String} formats: *