/*
* 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
*/
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 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
byte[] encoding;
/**
* 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) {
final Object[] values = (Object[]) in.content;
final boolean[] issuerUniqueID = (values[7] == null) ? null
: ((BitString) values[7]).toBooleanArray();
final 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) {
final 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;
}
};
/**
* Constructs the instance of TBSCertificate without optional fields
* (issuerUniqueID, subjectUniqueID, extensions)
*
* @param version
* : int
* @param serialNumber
* : BigInteger
* @param signature
* : AlgorithmIdentifier
* @param issuer
* : Name
* @param validity
* : Validity
* @param subject
* : Name
* @param subjectPublicKeyInfo
* : SubjectPublicKeyInfo
*/
public TBSCertificate(int version, BigInteger serialNumber,
AlgorithmIdentifier signature, Name issuer, Validity validity,
Name subject, SubjectPublicKeyInfo subjectPublicKeyInfo) {
this(version, serialNumber, signature, issuer, validity, subject,
subjectPublicKeyInfo, null, null, null);
}
/**
* TODO
*
* @param version
* : int
* @param serialNumber
* : BigInteger
* @param signature
* : AlgorithmIdentifier
* @param issuer
* : Name
* @param validity
* : Validity
* @param subject
* : Name
* @param subjectPublicKeyInfo
* : SubjectPublicKeyInfo
* @param issuerUniqueID
* : byte[]
* @param subjectUniqueID
* : byte[]
* @param extensions
* : Extensions
*/
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;
}
//
// TODO
// @param version: int
// @param serialNumber: BigInteger
// @param signature: AlgorithmIdentifier
// @param issuer: Name
// @param validity: Validity
// @param subject: Name
// @param subjectPublicKeyInfo: SubjectPublicKeyInfo
// @param issuerUniqueID: byte[]
// @param subjectUniqueID: byte[]
// @param extensions: Extensions
// @param encoding: byte[]
//
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;
}
/**
* Places the string representation into the StringBuffer object.
*/
public void dumpValue(StringBuffer buffer) {
buffer.append('[');
buffer.append("\n Version: V").append(version + 1); //$NON-NLS-1$
buffer.append("\n Subject: ") //$NON-NLS-1$
.append(subject.getName(X500Principal.RFC2253));
buffer.append("\n Signature Algorithm: "); //$NON-NLS-1$
signature.dumpValue(buffer);
buffer.append("\n Key: "); //$NON-NLS-1$
buffer.append(subjectPublicKeyInfo.getPublicKey().toString());
buffer.append("\n Validity: [From: "); //$NON-NLS-1$
buffer.append(validity.getNotBefore());
buffer.append("\n To: "); //$NON-NLS-1$
buffer.append(validity.getNotAfter()).append(']');
buffer.append("\n Issuer: "); //$NON-NLS-1$
buffer.append(issuer.getName(X500Principal.RFC2253));
buffer.append("\n Serial Number: "); //$NON-NLS-1$
buffer.append(serialNumber);
if (issuerUniqueID != null) {
buffer.append("\n Issuer Id: "); //$NON-NLS-1$
for (final boolean element : issuerUniqueID) {
buffer.append(element ? '1' : '0');
}
}
if (subjectUniqueID != null) {
buffer.append("\n Subject Id: "); //$NON-NLS-1$
for (final boolean element : subjectUniqueID) {
buffer.append(element ? '1' : '0');
}
}
if (extensions != null) {
buffer.append("\n\n Extensions: "); //$NON-NLS-1$
buffer.append("[\n"); //$NON-NLS-1$
extensions.dumpValue(buffer, " "); //$NON-NLS-1$
buffer.append(" ]"); //$NON-NLS-1$
}
buffer.append("\n]"); //$NON-NLS-1$
}
/**
* Returns ASN.1 encoded form of this X.509 TBSCertificate value.
*
* @return a byte array containing ASN.1 encode form.
*/
public byte[] getEncoded() {
if (encoding == null) {
encoding = ASN1.encode(this);
}
return encoding;
}
/**
* Returns the value of extensions field of the structure.
*
* @return extensions
*/
public Extensions getExtensions() {
return extensions;
}
/**
* Returns the value of issuer field of the structure.
*
* @return issuer
*/
public Name getIssuer() {
return issuer;
}
/**
* Returns the value of issuerUniqueID field of the structure.
*
* @return issuerUniqueID
*/
public boolean[] getIssuerUniqueID() {
return issuerUniqueID;
}
/**
* Returns the value of serialNumber field of the structure.
*
* @return serialNumber
*/
public BigInteger getSerialNumber() {
return serialNumber;
}
/**
* Returns the value of signature field of the structure.
*
* @return signature
*/
public AlgorithmIdentifier getSignature() {
return signature;
}
/**
* Returns the value of subject field of the structure.
*
* @return subject
*/
public Name getSubject() {
return subject;
}
/**
* Returns the value of subjectPublicKeyInfo field of the structure.
*
* @return subjectPublicKeyInfo
*/
public SubjectPublicKeyInfo getSubjectPublicKeyInfo() {
return subjectPublicKeyInfo;
}
/**
* Returns the value of subjectUniqueID field of the structure.
*
* @return subjectUniqueID
*/
public boolean[] getSubjectUniqueID() {
return subjectUniqueID;
}
/**
* Returns the value of validity field of the structure.
*
* @return validity
*/
public Validity getValidity() {
return validity;
}
/**
* Returns the value of version field of the structure.
*
* @return version
*/
public int getVersion() {
return version;
}
}