All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.java.security.PKCS12Attribute Maven / Gradle / Ivy

Go to download

A library jar that provides APIs for Applications written for the Google Android Platform.

There is a newer version: 15-robolectric-12650502
Show newest version
/*
 * Copyright (c) 2013, 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: *
    *
  • the DER encoding of a basic ASN.1 type that has a natural * string representation is returned as the string itself. * Such types are currently limited to BOOLEAN, INTEGER, * OBJECT IDENTIFIER, UTCTime, GeneralizedTime and the * following six ASN.1 string types: UTF8String, * PrintableString, T61String, IA5String, BMPString and * GeneralString. *
  • the DER encoding of any other ASN.1 type is not decoded but * returned as a binary 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[])}. * * @return the attribute value's string encoding */ @Override public String getValue() { return value; } /** * Returns the attribute's ASN.1 DER encoding. * * @return a clone of the attribute's DER encoding */ public byte[] getEncoded() { return encoded.clone(); } /** * Compares this {@code PKCS12Attribute} and a specified object for * equality. * * @param obj the comparison object * * @return true if {@code obj} is a {@code PKCS12Attribute} and * their DER encodings are equal. */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof PKCS12Attribute)) { return false; } return Arrays.equals(encoded, ((PKCS12Attribute) obj).getEncoded()); } /** * Returns the hashcode for this {@code PKCS12Attribute}. * The hash code is computed from its DER encoding. * * @return the hash code */ @Override public int hashCode() { if (hashValue == -1) { Arrays.hashCode(encoded); } return hashValue; } /** * Returns a string representation of this {@code PKCS12Attribute}. * * @return a name/value pair separated by an 'equals' symbol */ @Override public String toString() { return (name + "=" + value); } private byte[] encode(ObjectIdentifier type, String[] values) throws IOException { DerOutputStream attribute = new DerOutputStream(); attribute.putOID(type); DerOutputStream attrContent = new DerOutputStream(); for (String value : values) { if (COLON_SEPARATED_HEX_PAIRS.matcher(value).matches()) { byte[] bytes = new BigInteger(value.replace(":", ""), 16).toByteArray(); if (bytes[0] == 0) { bytes = Arrays.copyOfRange(bytes, 1, bytes.length); } attrContent.putOctetString(bytes); } else { attrContent.putUTF8String(value); } } attribute.write(DerValue.tag_Set, attrContent); DerOutputStream attributeValue = new DerOutputStream(); attributeValue.write(DerValue.tag_Sequence, attribute); return attributeValue.toByteArray(); } private void parse(byte[] encoded) throws IOException { DerInputStream attributeValue = new DerInputStream(encoded); DerValue[] attrSeq = attributeValue.getSequence(2); ObjectIdentifier type = attrSeq[0].getOID(); DerInputStream attrContent = new DerInputStream(attrSeq[1].toByteArray()); DerValue[] attrValueSet = attrContent.getSet(1); String[] values = new String[attrValueSet.length]; String printableString; for (int i = 0; i < attrValueSet.length; i++) { if (attrValueSet[i].tag == DerValue.tag_OctetString) { values[i] = Debug.toString(attrValueSet[i].getOctetString()); } else if ((printableString = attrValueSet[i].getAsString()) != null) { values[i] = printableString; } else if (attrValueSet[i].tag == DerValue.tag_ObjectId) { values[i] = attrValueSet[i].getOID().toString(); } else if (attrValueSet[i].tag == DerValue.tag_GeneralizedTime) { values[i] = attrValueSet[i].getGeneralizedTime().toString(); } else if (attrValueSet[i].tag == DerValue.tag_UtcTime) { values[i] = attrValueSet[i].getUTCTime().toString(); } else if (attrValueSet[i].tag == DerValue.tag_Integer) { values[i] = attrValueSet[i].getBigInteger().toString(); } else if (attrValueSet[i].tag == DerValue.tag_Boolean) { values[i] = String.valueOf(attrValueSet[i].getBoolean()); } else { values[i] = Debug.toString(attrValueSet[i].getDataBytes()); } } this.name = type.toString(); this.value = values.length == 1 ? values[0] : Arrays.toString(values); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy