
net.named_data.jndn.security.certificate.Certificate Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jndn-android-with-async-io Show documentation
Show all versions of jndn-android-with-async-io Show documentation
jNDN is a new implementation of a Named Data Networking client library written in Java. It is wire format compatible with the new NDN-TLV encoding, with NDNx and PARC's CCNx.
/**
* Copyright (C) 2014-2017 Regents of the University of California.
* @author: Jeff Thompson
* @author: From PyNDN certificate.py by Adeola Bannis .
* @author: Originally from code in ndn-cxx by Yingdi Yu
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
* A copy of the GNU Lesser General Public License is in the file COPYING.
*/
package net.named_data.jndn.security.certificate;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import net.named_data.jndn.ContentType;
import net.named_data.jndn.Data;
import net.named_data.jndn.Sha256WithRsaSignature;
import net.named_data.jndn.encoding.EncodingException;
import net.named_data.jndn.encoding.WireFormat;
import net.named_data.jndn.encoding.der.DerDecodingException;
import net.named_data.jndn.encoding.der.DerEncodingException;
import net.named_data.jndn.encoding.der.DerNode;
import net.named_data.jndn.encoding.der.DerNode.DerBoolean;
import net.named_data.jndn.encoding.der.DerNode.DerGeneralizedTime;
import net.named_data.jndn.encoding.der.DerNode.DerSequence;
import net.named_data.jndn.security.UnrecognizedKeyFormatException;
import net.named_data.jndn.util.Blob;
import net.named_data.jndn.util.Common;
public class Certificate extends Data {
/**
* The default constructor.
*/
public Certificate()
{
}
/**
* Create a Certificate from the content in the data packet.
* @param data The data packet with the content to decode.
*/
public Certificate(Data data) throws DerDecodingException
{
super(data);
decode();
}
/**
* Encode the contents of the certificate in DER format and set the Content
* and MetaInfo fields.
*/
public final void
encode() throws DerEncodingException, DerDecodingException
{
DerNode root = toDer();
setContent(root.encode());
getMetaInfo().setType(ContentType.KEY);
}
/**
* Override to call the base class wireDecode then populate the certificate
* fields.
* @param input The input byte array to be decoded as an immutable Blob.
* @param wireFormat A WireFormat object used to decode the input.
*/
public void
wireDecode(Blob input, WireFormat wireFormat)
throws EncodingException
{
super.wireDecode(input, wireFormat);
try {
decode();
} catch (DerDecodingException ex) {
throw new EncodingException(ex.getMessage());
}
}
/**
* Add a subject description.
* @param description The description to be added.
*/
public final void
addSubjectDescription(CertificateSubjectDescription description)
{
subjectDescriptionList_.add(description);
}
// List of CertificateSubjectDescription.
public final List
getSubjectDescriptionList()
{
return subjectDescriptionList_;
}
/**
* Add a certificate extension.
* @param extension the extension to be added
*/
public final void
addExtension(CertificateExtension extension)
{
extensionList_.add(extension);
}
// List of CertificateExtension.
public final List
getExtensionList()
{
return extensionList_;
}
public final void
setNotBefore(double notBefore)
{
notBefore_ = notBefore;
}
public final double
getNotBefore()
{
return notBefore_;
}
public final void
setNotAfter(double notAfter)
{
notAfter_ = notAfter;
}
public final double
getNotAfter()
{
return notAfter_;
}
public final void
setPublicKeyInfo(PublicKey key)
{
key_ = key;
}
public final PublicKey
getPublicKeyInfo()
{
return key_;
}
/**
* Get the public key DER encoding.
* @return The DER encoding Blob.
* @throws Error if the public key is not set.
*/
public final Blob
getPublicKeyDer()
{
if (key_.getKeyDer().isNull())
throw new Error("The public key is not set");
return key_.getKeyDer();
}
/**
* Check if the certificate is valid.
* @return True if the current time is earlier than notBefore.
*/
public final boolean
isTooEarly()
{
double now = Common.getNowMilliseconds();
return now < getNotBefore();
}
/**
* Check if the certificate is valid.
* @return True if the current time is later than notAfter.
*/
public final boolean
isTooLate()
{
double now = Common.getNowMilliseconds();
return now > getNotAfter();
}
public final boolean
isInValidityPeriod(double time)
{
// Debug: Generalize this from Sha256WithRsaSignature.
return ((Sha256WithRsaSignature)getSignature()).getValidityPeriod().isValid
(time);
}
/**
* Encode the certificate fields in DER format.
* @return The DER encoded contents of the certificate.
*/
private DerSequence
toDer() throws DerEncodingException, DerDecodingException
{
DerSequence root = new DerSequence();
DerSequence validity = new DerSequence();
DerGeneralizedTime notBefore = new DerGeneralizedTime(getNotBefore());
DerGeneralizedTime notAfter = new DerGeneralizedTime(getNotAfter());
validity.addChild(notBefore);
validity.addChild(notAfter);
root.addChild(validity);
DerSequence subjectList = new DerSequence();
for (int i = 0; i < subjectDescriptionList_.size(); ++i)
subjectList.addChild(((CertificateSubjectDescription)subjectDescriptionList_.get(i)).toDer());
root.addChild(subjectList);
root.addChild(key_.toDer());
if (extensionList_.size() > 0) {
DerSequence extensionList = new DerSequence();
for (int i = 0; i < extensionList_.size(); ++i)
extensionList.addChild(((CertificateExtension)extensionList_.get(i)).toDer());
root.addChild(extensionList);
}
return root;
}
/**
* Populate the fields by the decoding DER data from the Content.
*/
private void
decode() throws DerDecodingException
{
DerNode parsedNode = DerNode.parse(getContent().buf());
// We need to ensure that there are:
// validity (notBefore, notAfter)
// subject list
// public key
// (optional) extension list
List rootChildren = parsedNode.getChildren();
// 1st: validity info
List validityChildren = DerNode.getSequence(rootChildren, 0).getChildren();
notBefore_ = (Double)((DerGeneralizedTime)validityChildren.get(0)).toVal();
notAfter_ = (Double)((DerGeneralizedTime)validityChildren.get(1)).toVal();
// 2nd: subjectList
List subjectChildren = DerNode.getSequence(rootChildren, 1).getChildren();
for (int i = 0; i < subjectChildren.size(); ++i) {
DerSequence sd = DerNode.getSequence(subjectChildren, i);
List descriptionChildren = sd.getChildren();
String oidStr = (String)((DerNode)descriptionChildren.get(0)).toVal();
String value = "" + ((Blob)((DerNode)descriptionChildren.get(1)).toVal());
addSubjectDescription(new CertificateSubjectDescription(oidStr, value));
}
// 3rd: public key
Blob publicKeyInfo = ((DerNode)rootChildren.get(2)).encode();
try {
key_ = new PublicKey(publicKeyInfo);
}
catch (UnrecognizedKeyFormatException ex) {
throw new DerDecodingException(ex.getMessage());
}
if (rootChildren.size() > 3) {
List extensionChildren = DerNode.getSequence(rootChildren, 3).getChildren();
for (int i = 0; i < extensionChildren.size(); ++i) {
DerSequence extInfo = DerNode.getSequence(extensionChildren, i);
List children = extInfo.getChildren();
String oidStr = (String)((DerNode)children.get(0)).toVal();
boolean isCritical = (Boolean)((DerBoolean)children.get(1)).toVal();
Blob value = (Blob)((DerNode)children.get(2)).toVal();
addExtension(new CertificateExtension(oidStr, isCritical, value));
}
}
}
public String
toString()
{
String s = "Certificate name:\n";
s += " " + getName().toUri() + "\n";
s += "Validity:\n";
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
String notBeforeStr = dateFormat.format
(Common.millisecondsSince1970ToDate((long)Math.round(getNotBefore())));
String notAfterStr = dateFormat.format
(Common.millisecondsSince1970ToDate((long)Math.round(getNotAfter())));
s += " NotBefore: " + notBeforeStr + "\n";
s += " NotAfter: " + notAfterStr + "\n";
for (int i = 0; i < subjectDescriptionList_.size(); ++i) {
CertificateSubjectDescription sd =
(CertificateSubjectDescription)subjectDescriptionList_.get(i);
s += "Subject Description:\n";
s += " " + sd.getOidString() + ": " + sd.getValue() + "\n";
}
s += "Public key bits:\n";
Blob keyDer = getPublicKeyDer();
String encodedKey = Common.base64Encode(keyDer.getImmutableArray());
for (int i = 0; i < encodedKey.length(); i += 64)
s += encodedKey.substring(i, Math.min(i + 64, encodedKey.length())) + "\n";
if (extensionList_.size() > 0) {
s += "Extensions:\n";
for (int i = 0; i < extensionList_.size(); ++i) {
CertificateExtension ext = (CertificateExtension)extensionList_.get(i);
s += " OID: " + ext.getOid() + "\n";
s += " Is critical: " + (ext.getIsCritical() ? 'Y' : 'N') + "\n";
s += " Value: " + ext.getValue().toHex() + "\n" ;
}
}
return s;
}
// Use ArrayList without generics so it works with older Java compilers.
private final ArrayList subjectDescriptionList_ = new ArrayList(); // of CertificateSubjectDescription
private final ArrayList extensionList_ = new ArrayList(); // of CertificateExtension
private double notBefore_ = Double.MAX_VALUE; // MillisecondsSince1970
private double notAfter_ = -Double.MAX_VALUE; // MillisecondsSince1970
private PublicKey key_ = new PublicKey();
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy