/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @author Alexander Y. Kleymenov * @version $Revision$ */ package org.apache.harmony.security.x509; import java.math.BigInteger; import javax.security.auth.x500.X500Principal; import org.apache.harmony.security.asn1.ASN1BitString; import org.apache.harmony.security.asn1.ASN1Explicit; import org.apache.harmony.security.asn1.ASN1Implicit; import org.apache.harmony.security.asn1.ASN1Integer; import org.apache.harmony.security.asn1.ASN1Sequence; import org.apache.harmony.security.asn1.ASN1Type; import org.apache.harmony.security.asn1.BerInputStream; import org.apache.harmony.security.asn1.BitString; import org.apache.harmony.security.x501.Name; /** * The class encapsulates the ASN.1 DER encoding/decoding work * with TBSCertificate structure which is the part of X.509 certificate * (as specified in RFC 3280 - * Internet X.509 Public Key Infrastructure. * Certificate and Certificate Revocation List (CRL) Profile. * http://www.ietf.org/rfc/rfc3280.txt): * * <pre> * TBSCertificate ::= SEQUENCE { * version [0] EXPLICIT Version DEFAULT v1, * serialNumber CertificateSerialNumber, * signature AlgorithmIdentifier, * issuer Name, * validity Validity, * subject Name, * subjectPublicKeyInfo SubjectPublicKeyInfo, * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, * -- If present, version MUST be v2 or v3 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, * -- If present, version MUST be v2 or v3 * extensions [3] EXPLICIT Extensions OPTIONAL * -- If present, version MUST be v3 * } * </pre> */ public final class TBSCertificate { /** the value of version field of the structure */ private final int version; /** the value of serialNumber field of the structure */ private final BigInteger serialNumber; /** the value of signature field of the structure */ private final AlgorithmIdentifier signature; /** the value of issuer field of the structure */ private final Name issuer; /** the value of validity field of the structure */ private final Validity validity; /** the value of subject field of the structure */ private final Name subject; /** the value of subjectPublicKeyInfo field of the structure */ private final SubjectPublicKeyInfo subjectPublicKeyInfo; /** the value of issuerUniqueID field of the structure */ private final boolean[] issuerUniqueID; /** the value of subjectUniqueID field of the structure */ private final boolean[] subjectUniqueID; /** the value of extensions field of the structure */ private final Extensions extensions; /** the ASN.1 encoded form of TBSCertificate */ private byte[] encoding; public TBSCertificate(int version, BigInteger serialNumber, AlgorithmIdentifier signature, Name issuer, Validity validity, Name subject, SubjectPublicKeyInfo subjectPublicKeyInfo, boolean[] issuerUniqueID, boolean[] subjectUniqueID, Extensions extensions) { this.version = version; this.serialNumber = serialNumber; this.signature = signature; this.issuer = issuer; this.validity = validity; this.subject = subject; this.subjectPublicKeyInfo = subjectPublicKeyInfo; this.issuerUniqueID = issuerUniqueID; this.subjectUniqueID = subjectUniqueID; this.extensions = extensions; } private TBSCertificate(int version, BigInteger serialNumber, AlgorithmIdentifier signature, Name issuer, Validity validity, Name subject, SubjectPublicKeyInfo subjectPublicKeyInfo, boolean[] issuerUniqueID, boolean[] subjectUniqueID, Extensions extensions, byte[] encoding) { this(version, serialNumber, signature, issuer, validity, subject, subjectPublicKeyInfo, issuerUniqueID, subjectUniqueID, extensions); this.encoding = encoding; } /** * Returns the value of version field of the structure. */ public int getVersion() { return version; } /** * Returns the value of serialNumber field of the structure. */ public BigInteger getSerialNumber() { return serialNumber; } /** * Returns the value of signature field of the structure. */ public AlgorithmIdentifier getSignature() { return signature; } /** * Returns the value of issuer field of the structure. */ public Name getIssuer() { return issuer; } /** * Returns the value of validity field of the structure. */ public Validity getValidity() { return validity; } /** * Returns the value of subject field of the structure. */ public Name getSubject() { return subject; } /** * Returns the value of subjectPublicKeyInfo field of the structure. */ public SubjectPublicKeyInfo getSubjectPublicKeyInfo() { return subjectPublicKeyInfo; } /** * Returns the value of issuerUniqueID field of the structure. */ public boolean[] getIssuerUniqueID() { return issuerUniqueID; } /** * Returns the value of subjectUniqueID field of the structure. */ public boolean[] getSubjectUniqueID() { return subjectUniqueID; } /** * Returns the value of extensions field of the structure. */ public Extensions getExtensions() { return extensions; } /** * Returns ASN.1 encoded form of this X.509 TBSCertificate value. */ public byte[] getEncoded() { if (encoding == null) { encoding = ASN1.encode(this); } return encoding; } public void dumpValue(StringBuilder sb) { sb.append('['); sb.append("\n Version: V").append(version+1); sb.append("\n Subject: ").append(subject.getName(X500Principal.RFC2253)); sb.append("\n Signature Algorithm: "); signature.dumpValue(sb); sb.append("\n Key: ").append(subjectPublicKeyInfo.getPublicKey().toString()); sb.append("\n Validity: [From: ").append(validity.getNotBefore()); sb.append("\n To: ").append(validity.getNotAfter()).append(']'); sb.append("\n Issuer: ").append(issuer.getName(X500Principal.RFC2253)); sb.append("\n Serial Number: ").append(serialNumber); if (issuerUniqueID != null) { sb.append("\n Issuer Id: "); for (boolean b : issuerUniqueID) { sb.append(b ? '1' : '0'); } } if (subjectUniqueID != null) { sb.append("\n Subject Id: "); for (boolean b : subjectUniqueID) { sb.append(b ? '1' : '0'); } } if (extensions != null) { sb.append("\n\n Extensions: "); sb.append("[\n"); extensions.dumpValue(sb, " "); sb.append(" ]"); } sb.append("\n]"); } /** * X.509 TBSCertificate encoder/decoder. */ public static final ASN1Sequence ASN1 = new ASN1Sequence(new ASN1Type[] { new ASN1Explicit(0, ASN1Integer.getInstance()), ASN1Integer.getInstance(), AlgorithmIdentifier.ASN1, Name.ASN1, Validity.ASN1, Name.ASN1, SubjectPublicKeyInfo.ASN1, new ASN1Implicit(1, ASN1BitString.getInstance()), new ASN1Implicit(2, ASN1BitString.getInstance()), new ASN1Explicit(3, Extensions.ASN1)}) { { setDefault(new byte[] {0}, 0); setOptional(7); setOptional(8); setOptional(9); } @Override protected Object getDecodedObject(BerInputStream in) { Object[] values = (Object[]) in.content; boolean[] issuerUniqueID = (values[7] == null) ? null : ((BitString) values[7]).toBooleanArray(); boolean[] subjectUniqueID = (values[8] == null) ? null : ((BitString) values[8]).toBooleanArray(); return new TBSCertificate( ASN1Integer.toIntValue(values[0]), new BigInteger((byte[]) values[1]), (AlgorithmIdentifier) values[2], (Name) values[3], (Validity) values[4], (Name) values[5], (SubjectPublicKeyInfo) values[6], issuerUniqueID, subjectUniqueID, (Extensions) values[9], in.getEncoded() ); } @Override protected void getValues(Object object, Object[] values) { TBSCertificate tbs = (TBSCertificate) object; values[0] = ASN1Integer.fromIntValue(tbs.version); values[1] = tbs.serialNumber.toByteArray(); values[2] = tbs.signature; values[3] = tbs.issuer; values[4] = tbs.validity; values[5] = tbs.subject; values[6] = tbs.subjectPublicKeyInfo; if (tbs.issuerUniqueID != null) { values[7] = new BitString(tbs.issuerUniqueID); } if (tbs.subjectUniqueID != null) { values[8] = new BitString(tbs.subjectUniqueID); } values[9] = tbs.extensions; } }; }