提交 76fc7f94 编写于 作者: M michaelm

Merge

...@@ -2351,6 +2351,64 @@ public class Collections { ...@@ -2351,6 +2351,64 @@ public class Collections {
} }
} }
/**
* Returns a dynamically typesafe view of the specified queue.
* Any attempt to insert an element of the wrong type will result in
* an immediate {@link ClassCastException}. Assuming a queue contains
* no incorrectly typed elements prior to the time a dynamically typesafe
* view is generated, and that all subsequent access to the queue
* takes place through the view, it is <i>guaranteed</i> that the
* queue cannot contain an incorrectly typed element.
*
* <p>A discussion of the use of dynamically typesafe views may be
* found in the documentation for the {@link #checkedCollection
* checkedCollection} method.
*
* <p>The returned queue will be serializable if the specified queue
* is serializable.
*
* <p>Since {@code null} is considered to be a value of any reference
* type, the returned queue permits insertion of {@code null} elements
* whenever the backing queue does.
*
* @param queue the queue for which a dynamically typesafe view is to be
* returned
* @param type the type of element that {@code queue} is permitted to hold
* @return a dynamically typesafe view of the specified queue
* @since 1.8
*/
public static <E> Queue<E> checkedQueue(Queue<E> queue, Class<E> type) {
return new CheckedQueue<>(queue, type);
}
/**
* @serial include
*/
static class CheckedQueue<E>
extends CheckedCollection<E>
implements Queue<E>, Serializable
{
private static final long serialVersionUID = 1433151992604707767L;
final Queue<E> queue;
CheckedQueue(Queue<E> queue, Class<E> elementType) {
super(queue, elementType);
this.queue = queue;
}
public E element() {return queue.element();}
public boolean equals(Object o) {return o == this || c.equals(o);}
public int hashCode() {return c.hashCode();}
public E peek() {return queue.peek();}
public E poll() {return queue.poll();}
public E remove() {return queue.remove();}
public boolean offer(E e) {
typeCheck(e);
return add(e);
}
}
/** /**
* Returns a dynamically typesafe view of the specified set. * Returns a dynamically typesafe view of the specified set.
* Any attempt to insert an element of the wrong type will result in * Any attempt to insert an element of the wrong type will result in
......
...@@ -27,6 +27,7 @@ package sun.security.pkcs; ...@@ -27,6 +27,7 @@ package sun.security.pkcs;
import java.io.*; import java.io.*;
import java.math.BigInteger; import java.math.BigInteger;
import java.net.URI;
import java.util.*; import java.util.*;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
...@@ -35,6 +36,7 @@ import java.security.cert.CRLException; ...@@ -35,6 +36,7 @@ import java.security.cert.CRLException;
import java.security.cert.CertificateFactory; import java.security.cert.CertificateFactory;
import java.security.*; import java.security.*;
import sun.security.timestamp.*;
import sun.security.util.*; import sun.security.util.*;
import sun.security.x509.AlgorithmId; import sun.security.x509.AlgorithmId;
import sun.security.x509.CertificateIssuerName; import sun.security.x509.CertificateIssuerName;
...@@ -68,6 +70,30 @@ public class PKCS7 { ...@@ -68,6 +70,30 @@ public class PKCS7 {
private Principal[] certIssuerNames; private Principal[] certIssuerNames;
/*
* Random number generator for creating nonce values
*/
private static final SecureRandom RANDOM;
static {
SecureRandom tmp = null;
try {
tmp = SecureRandom.getInstance("SHA1PRNG");
} catch (NoSuchAlgorithmException e) {
// should not happen
}
RANDOM = tmp;
}
/*
* Object identifier for the timestamping key purpose.
*/
private static final String KP_TIMESTAMPING_OID = "1.3.6.1.5.5.7.3.8";
/*
* Object identifier for extendedKeyUsage extension
*/
private static final String EXTENDED_KEY_USAGE_OID = "2.5.29.37";
/** /**
* Unmarshals a PKCS7 block from its encoded form, parsing the * Unmarshals a PKCS7 block from its encoded form, parsing the
* encoded bytes from the InputStream. * encoded bytes from the InputStream.
...@@ -733,4 +759,164 @@ public class PKCS7 { ...@@ -733,4 +759,164 @@ public class PKCS7 {
public boolean isOldStyle() { public boolean isOldStyle() {
return this.oldStyle; return this.oldStyle;
} }
/**
* Assembles a PKCS #7 signed data message that optionally includes a
* signature timestamp.
*
* @param signature the signature bytes
* @param signerChain the signer's X.509 certificate chain
* @param content the content that is signed; specify null to not include
* it in the PKCS7 data
* @param signatureAlgorithm the name of the signature algorithm
* @param tsaURI the URI of the Timestamping Authority; or null if no
* timestamp is requested
* @return the bytes of the encoded PKCS #7 signed data message
* @throws NoSuchAlgorithmException The exception is thrown if the signature
* algorithm is unrecognised.
* @throws CertificateException The exception is thrown if an error occurs
* while processing the signer's certificate or the TSA's
* certificate.
* @throws IOException The exception is thrown if an error occurs while
* generating the signature timestamp or while generating the signed
* data message.
*/
public static byte[] generateSignedData(byte[] signature,
X509Certificate[] signerChain,
byte[] content,
String signatureAlgorithm,
URI tsaURI)
throws CertificateException, IOException, NoSuchAlgorithmException
{
// Generate the timestamp token
PKCS9Attributes unauthAttrs = null;
if (tsaURI != null) {
// Timestamp the signature
HttpTimestamper tsa = new HttpTimestamper(tsaURI);
byte[] tsToken = generateTimestampToken(tsa, signature);
// Insert the timestamp token into the PKCS #7 signer info element
// (as an unsigned attribute)
unauthAttrs =
new PKCS9Attributes(new PKCS9Attribute[]{
new PKCS9Attribute(
PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_STR,
tsToken)});
}
// Create the SignerInfo
X500Name issuerName =
X500Name.asX500Name(signerChain[0].getIssuerX500Principal());
BigInteger serialNumber = signerChain[0].getSerialNumber();
String encAlg = AlgorithmId.getEncAlgFromSigAlg(signatureAlgorithm);
String digAlg = AlgorithmId.getDigAlgFromSigAlg(signatureAlgorithm);
SignerInfo signerInfo = new SignerInfo(issuerName, serialNumber,
AlgorithmId.get(digAlg), null,
AlgorithmId.get(encAlg),
signature, unauthAttrs);
// Create the PKCS #7 signed data message
SignerInfo[] signerInfos = {signerInfo};
AlgorithmId[] algorithms = {signerInfo.getDigestAlgorithmId()};
// Include or exclude content
ContentInfo contentInfo = (content == null)
? new ContentInfo(ContentInfo.DATA_OID, null)
: new ContentInfo(content);
PKCS7 pkcs7 = new PKCS7(algorithms, contentInfo,
signerChain, signerInfos);
ByteArrayOutputStream p7out = new ByteArrayOutputStream();
pkcs7.encodeSignedData(p7out);
return p7out.toByteArray();
}
/**
* Requests, processes and validates a timestamp token from a TSA using
* common defaults. Uses the following defaults in the timestamp request:
* SHA-1 for the hash algorithm, a 64-bit nonce, and request certificate
* set to true.
*
* @param tsa the timestamping authority to use
* @param toBeTimestamped the token that is to be timestamped
* @return the encoded timestamp token
* @throws IOException The exception is thrown if an error occurs while
* communicating with the TSA.
* @throws CertificateException The exception is thrown if the TSA's
* certificate is not permitted for timestamping.
*/
private static byte[] generateTimestampToken(Timestamper tsa,
byte[] toBeTimestamped)
throws IOException, CertificateException
{
// Generate a timestamp
MessageDigest messageDigest = null;
TSRequest tsQuery = null;
try {
// SHA-1 is always used.
messageDigest = MessageDigest.getInstance("SHA-1");
tsQuery = new TSRequest(toBeTimestamped, messageDigest);
} catch (NoSuchAlgorithmException e) {
// ignore
}
// Generate a nonce
BigInteger nonce = null;
if (RANDOM != null) {
nonce = new BigInteger(64, RANDOM);
tsQuery.setNonce(nonce);
}
tsQuery.requestCertificate(true);
TSResponse tsReply = tsa.generateTimestamp(tsQuery);
int status = tsReply.getStatusCode();
// Handle TSP error
if (status != 0 && status != 1) {
throw new IOException("Error generating timestamp: " +
tsReply.getStatusCodeAsText() + " " +
tsReply.getFailureCodeAsText());
}
PKCS7 tsToken = tsReply.getToken();
TimestampToken tst = tsReply.getTimestampToken();
if (!tst.getHashAlgorithm().getName().equals("SHA")) {
throw new IOException("Digest algorithm not SHA-1 in "
+ "timestamp token");
}
if (!MessageDigest.isEqual(tst.getHashedMessage(),
tsQuery.getHashedMessage())) {
throw new IOException("Digest octets changed in timestamp token");
}
BigInteger replyNonce = tst.getNonce();
if (replyNonce == null && nonce != null) {
throw new IOException("Nonce missing in timestamp token");
}
if (replyNonce != null && !replyNonce.equals(nonce)) {
throw new IOException("Nonce changed in timestamp token");
}
// Examine the TSA's certificate (if present)
for (SignerInfo si: tsToken.getSignerInfos()) {
X509Certificate cert = si.getCertificate(tsToken);
if (cert == null) {
// Error, we've already set tsRequestCertificate = true
throw new CertificateException(
"Certificate not included in timestamp token");
} else {
if (!cert.getCriticalExtensionOIDs().contains(
EXTENDED_KEY_USAGE_OID)) {
throw new CertificateException(
"Certificate is not valid for timestamping");
}
List<String> keyPurposes = cert.getExtendedKeyUsage();
if (keyPurposes == null ||
!keyPurposes.contains(KP_TIMESTAMPING_OID)) {
throw new CertificateException(
"Certificate is not valid for timestamping");
}
}
}
return tsReply.getEncodedToken();
}
} }
...@@ -28,10 +28,14 @@ package sun.security.pkcs; ...@@ -28,10 +28,14 @@ package sun.security.pkcs;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertPath;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.security.*; import java.security.*;
import java.util.ArrayList; import java.util.ArrayList;
import sun.security.timestamp.TimestampToken;
import sun.security.util.*; import sun.security.util.*;
import sun.security.x509.AlgorithmId; import sun.security.x509.AlgorithmId;
import sun.security.x509.X500Name; import sun.security.x509.X500Name;
...@@ -51,6 +55,8 @@ public class SignerInfo implements DerEncoder { ...@@ -51,6 +55,8 @@ public class SignerInfo implements DerEncoder {
AlgorithmId digestAlgorithmId; AlgorithmId digestAlgorithmId;
AlgorithmId digestEncryptionAlgorithmId; AlgorithmId digestEncryptionAlgorithmId;
byte[] encryptedDigest; byte[] encryptedDigest;
Timestamp timestamp;
private boolean hasTimestamp = true;
PKCS9Attributes authenticatedAttributes; PKCS9Attributes authenticatedAttributes;
PKCS9Attributes unauthenticatedAttributes; PKCS9Attributes unauthenticatedAttributes;
...@@ -442,6 +448,62 @@ public class SignerInfo implements DerEncoder { ...@@ -442,6 +448,62 @@ public class SignerInfo implements DerEncoder {
return unauthenticatedAttributes; return unauthenticatedAttributes;
} }
/*
* Extracts a timestamp from a PKCS7 SignerInfo.
*
* Examines the signer's unsigned attributes for a
* <tt>signatureTimestampToken</tt> attribute. If present,
* then it is parsed to extract the date and time at which the
* timestamp was generated.
*
* @param info A signer information element of a PKCS 7 block.
*
* @return A timestamp token or null if none is present.
* @throws IOException if an error is encountered while parsing the
* PKCS7 data.
* @throws NoSuchAlgorithmException if an error is encountered while
* verifying the PKCS7 object.
* @throws SignatureException if an error is encountered while
* verifying the PKCS7 object.
* @throws CertificateException if an error is encountered while generating
* the TSA's certpath.
*/
public Timestamp getTimestamp()
throws IOException, NoSuchAlgorithmException, SignatureException,
CertificateException
{
if (timestamp != null || !hasTimestamp)
return timestamp;
if (unauthenticatedAttributes == null) {
hasTimestamp = false;
return null;
}
PKCS9Attribute tsTokenAttr =
unauthenticatedAttributes.getAttribute(
PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID);
if (tsTokenAttr == null) {
hasTimestamp = false;
return null;
}
PKCS7 tsToken = new PKCS7((byte[])tsTokenAttr.getValue());
// Extract the content (an encoded timestamp token info)
byte[] encTsTokenInfo = tsToken.getContentInfo().getData();
// Extract the signer (the Timestamping Authority)
// while verifying the content
SignerInfo[] tsa = tsToken.verify(encTsTokenInfo);
// Expect only one signer
ArrayList<X509Certificate> chain = tsa[0].getCertificateChain(tsToken);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
CertPath tsaChain = cf.generateCertPath(chain);
// Create a timestamp token info object
TimestampToken tsTokenInfo = new TimestampToken(encTsTokenInfo);
// Create a timestamp object
timestamp = new Timestamp(tsTokenInfo.getDate(), tsaChain);
return timestamp;
}
public String toString() { public String toString() {
HexDumpEncoder hexDump = new HexDumpEncoder(); HexDumpEncoder hexDump = new HexDumpEncoder();
...@@ -467,5 +529,4 @@ public class SignerInfo implements DerEncoder { ...@@ -467,5 +529,4 @@ public class SignerInfo implements DerEncoder {
} }
return out; return out;
} }
} }
...@@ -28,13 +28,13 @@ package sun.security.timestamp; ...@@ -28,13 +28,13 @@ package sun.security.timestamp;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.net.URI;
import java.net.URL; import java.net.URL;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.util.List; import java.util.*;
import java.util.Map;
import java.util.Set;
import sun.misc.IOUtils; import sun.misc.IOUtils;
import sun.security.util.Debug;
/** /**
* A timestamper that communicates with a Timestamping Authority (TSA) * A timestamper that communicates with a Timestamping Authority (TSA)
...@@ -58,20 +58,23 @@ public class HttpTimestamper implements Timestamper { ...@@ -58,20 +58,23 @@ public class HttpTimestamper implements Timestamper {
private static final String TS_REPLY_MIME_TYPE = private static final String TS_REPLY_MIME_TYPE =
"application/timestamp-reply"; "application/timestamp-reply";
private static final boolean DEBUG = false; private static final Debug debug = Debug.getInstance("ts");
/* /*
* HTTP URL identifying the location of the TSA * HTTP URI identifying the location of the TSA
*/ */
private String tsaUrl = null; private URI tsaURI = null;
/** /**
* Creates a timestamper that connects to the specified TSA. * Creates a timestamper that connects to the specified TSA.
* *
* @param tsa The location of the TSA. It must be an HTTP URL. * @param tsa The location of the TSA. It must be an HTTP URI.
* @throws IllegalArgumentException if tsaURI is not an HTTP URI
*/ */
public HttpTimestamper(String tsaUrl) { public HttpTimestamper(URI tsaURI) {
this.tsaUrl = tsaUrl; if (!tsaURI.getScheme().equalsIgnoreCase("http"))
throw new IllegalArgumentException("TSA must be an HTTP URI");
this.tsaURI = tsaURI;
} }
/** /**
...@@ -85,7 +88,7 @@ public class HttpTimestamper implements Timestamper { ...@@ -85,7 +88,7 @@ public class HttpTimestamper implements Timestamper {
public TSResponse generateTimestamp(TSRequest tsQuery) throws IOException { public TSResponse generateTimestamp(TSRequest tsQuery) throws IOException {
HttpURLConnection connection = HttpURLConnection connection =
(HttpURLConnection) new URL(tsaUrl).openConnection(); (HttpURLConnection) tsaURI.toURL().openConnection();
connection.setDoOutput(true); connection.setDoOutput(true);
connection.setUseCaches(false); // ignore cache connection.setUseCaches(false); // ignore cache
connection.setRequestProperty("Content-Type", TS_QUERY_MIME_TYPE); connection.setRequestProperty("Content-Type", TS_QUERY_MIME_TYPE);
...@@ -93,15 +96,15 @@ public class HttpTimestamper implements Timestamper { ...@@ -93,15 +96,15 @@ public class HttpTimestamper implements Timestamper {
// Avoids the "hang" when a proxy is required but none has been set. // Avoids the "hang" when a proxy is required but none has been set.
connection.setConnectTimeout(CONNECT_TIMEOUT); connection.setConnectTimeout(CONNECT_TIMEOUT);
if (DEBUG) { if (debug != null) {
Set<Map.Entry<String, List<String>>> headers = Set<Map.Entry<String, List<String>>> headers =
connection.getRequestProperties().entrySet(); connection.getRequestProperties().entrySet();
System.out.println(connection.getRequestMethod() + " " + tsaUrl + debug.println(connection.getRequestMethod() + " " + tsaURI +
" HTTP/1.1"); " HTTP/1.1");
for (Map.Entry<String, List<String>> entry : headers) { for (Map.Entry<String, List<String>> e : headers) {
System.out.println(" " + entry); debug.println(" " + e);
} }
System.out.println(); debug.println();
} }
connection.connect(); // No HTTP authentication is performed connection.connect(); // No HTTP authentication is performed
...@@ -112,8 +115,8 @@ public class HttpTimestamper implements Timestamper { ...@@ -112,8 +115,8 @@ public class HttpTimestamper implements Timestamper {
byte[] request = tsQuery.encode(); byte[] request = tsQuery.encode();
output.write(request, 0, request.length); output.write(request, 0, request.length);
output.flush(); output.flush();
if (DEBUG) { if (debug != null) {
System.out.println("sent timestamp query (length=" + debug.println("sent timestamp query (length=" +
request.length + ")"); request.length + ")");
} }
} finally { } finally {
...@@ -127,17 +130,17 @@ public class HttpTimestamper implements Timestamper { ...@@ -127,17 +130,17 @@ public class HttpTimestamper implements Timestamper {
byte[] replyBuffer = null; byte[] replyBuffer = null;
try { try {
input = new BufferedInputStream(connection.getInputStream()); input = new BufferedInputStream(connection.getInputStream());
if (DEBUG) { if (debug != null) {
String header = connection.getHeaderField(0); String header = connection.getHeaderField(0);
System.out.println(header); debug.println(header);
int i = 1; int i = 1;
while ((header = connection.getHeaderField(i)) != null) { while ((header = connection.getHeaderField(i)) != null) {
String key = connection.getHeaderFieldKey(i); String key = connection.getHeaderFieldKey(i);
System.out.println(" " + ((key==null) ? "" : key + ": ") + debug.println(" " + ((key==null) ? "" : key + ": ") +
header); header);
i++; i++;
} }
System.out.println(); debug.println();
} }
verifyMimeType(connection.getContentType()); verifyMimeType(connection.getContentType());
...@@ -145,8 +148,8 @@ public class HttpTimestamper implements Timestamper { ...@@ -145,8 +148,8 @@ public class HttpTimestamper implements Timestamper {
int contentLength = connection.getContentLength(); int contentLength = connection.getContentLength();
replyBuffer = IOUtils.readFully(input, contentLength, false); replyBuffer = IOUtils.readFully(input, contentLength, false);
if (DEBUG) { if (debug != null) {
System.out.println("received timestamp response (length=" + debug.println("received timestamp response (length=" +
total + ")"); total + ")");
} }
} finally { } finally {
......
/* /*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -27,10 +27,13 @@ package sun.security.timestamp; ...@@ -27,10 +27,13 @@ package sun.security.timestamp;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Extension; import java.security.cert.X509Extension;
import sun.security.util.DerValue; import sun.security.util.DerValue;
import sun.security.util.DerOutputStream; import sun.security.util.DerOutputStream;
import sun.security.util.ObjectIdentifier; import sun.security.util.ObjectIdentifier;
import sun.security.x509.AlgorithmId;
/** /**
* This class provides a timestamp request, as defined in * This class provides a timestamp request, as defined in
...@@ -64,24 +67,9 @@ import sun.security.util.ObjectIdentifier; ...@@ -64,24 +67,9 @@ import sun.security.util.ObjectIdentifier;
public class TSRequest { public class TSRequest {
private static final ObjectIdentifier SHA1_OID;
private static final ObjectIdentifier MD5_OID;
static {
ObjectIdentifier sha1 = null;
ObjectIdentifier md5 = null;
try {
sha1 = new ObjectIdentifier("1.3.14.3.2.26");
md5 = new ObjectIdentifier("1.2.840.113549.2.5");
} catch (IOException ioe) {
// should not happen
}
SHA1_OID = sha1;
MD5_OID = md5;
}
private int version = 1; private int version = 1;
private ObjectIdentifier hashAlgorithmId = null; private AlgorithmId hashAlgorithmId = null;
private byte[] hashValue; private byte[] hashValue;
...@@ -94,30 +82,21 @@ public class TSRequest { ...@@ -94,30 +82,21 @@ public class TSRequest {
private X509Extension[] extensions = null; private X509Extension[] extensions = null;
/** /**
* Constructs a timestamp request for the supplied hash value.. * Constructs a timestamp request for the supplied data.
* *
* @param hashValue The hash value. This is the data to be timestamped. * @param toBeTimeStamped The data to be timestamped.
* @param hashAlgorithm The name of the hash algorithm. * @param messageDigest The MessageDigest of the hash algorithm to use.
* @throws NoSuchAlgorithmException if the hash algorithm is not supported
*/ */
public TSRequest(byte[] hashValue, String hashAlgorithm) { public TSRequest(byte[] toBeTimeStamped, MessageDigest messageDigest)
throws NoSuchAlgorithmException {
// Check the common hash algorithms this.hashAlgorithmId = AlgorithmId.get(messageDigest.getAlgorithm());
if ("MD5".equalsIgnoreCase(hashAlgorithm)) { this.hashValue = messageDigest.digest(toBeTimeStamped);
hashAlgorithmId = MD5_OID; }
// Check that the hash value matches the hash algorithm
assert hashValue.length == 16;
} else if ("SHA-1".equalsIgnoreCase(hashAlgorithm) ||
"SHA".equalsIgnoreCase(hashAlgorithm) ||
"SHA1".equalsIgnoreCase(hashAlgorithm)) {
hashAlgorithmId = SHA1_OID;
// Check that the hash value matches the hash algorithm
assert hashValue.length == 20;
} public byte[] getHashedMessage() {
// Clone the hash value return hashValue.clone();
this.hashValue = new byte[hashValue.length];
System.arraycopy(hashValue, 0, this.hashValue, 0, hashValue.length);
} }
/** /**
...@@ -176,9 +155,7 @@ public class TSRequest { ...@@ -176,9 +155,7 @@ public class TSRequest {
// encode messageImprint // encode messageImprint
DerOutputStream messageImprint = new DerOutputStream(); DerOutputStream messageImprint = new DerOutputStream();
DerOutputStream hashAlgorithm = new DerOutputStream(); hashAlgorithmId.encode(messageImprint);
hashAlgorithm.putOID(hashAlgorithmId);
messageImprint.write(DerValue.tag_Sequence, hashAlgorithm);
messageImprint.putOctetString(hashValue); messageImprint.putOctetString(hashValue);
request.write(DerValue.tag_Sequence, messageImprint); request.write(DerValue.tag_Sequence, messageImprint);
......
...@@ -27,6 +27,7 @@ package sun.security.timestamp; ...@@ -27,6 +27,7 @@ package sun.security.timestamp;
import java.io.IOException; import java.io.IOException;
import sun.security.pkcs.PKCS7; import sun.security.pkcs.PKCS7;
import sun.security.util.Debug;
import sun.security.util.DerValue; import sun.security.util.DerValue;
/** /**
...@@ -175,18 +176,20 @@ public class TSResponse { ...@@ -175,18 +176,20 @@ public class TSResponse {
*/ */
public static final int SYSTEM_FAILURE = 25; public static final int SYSTEM_FAILURE = 25;
private static final boolean DEBUG = false; private static final Debug debug = Debug.getInstance("ts");
private int status; private int status;
private String[] statusString = null; private String[] statusString = null;
private int failureInfo = -1; private boolean[] failureInfo = null;
private byte[] encodedTsToken = null; private byte[] encodedTsToken = null;
private PKCS7 tsToken = null; private PKCS7 tsToken = null;
private TimestampToken tstInfo;
/** /**
* Constructs an object to store the response to a timestamp request. * Constructs an object to store the response to a timestamp request.
* *
...@@ -215,11 +218,11 @@ public class TSResponse { ...@@ -215,11 +218,11 @@ public class TSResponse {
} }
/** /**
* Retrieve the failure code returned by the TSA. * Retrieve the failure info returned by the TSA.
* *
* @return If -1 then no failure code was received. * @return the failure info, or null if no failure code was received.
*/ */
public int getFailureCode() { public boolean[] getFailureInfo() {
return failureInfo; return failureInfo;
} }
...@@ -250,42 +253,38 @@ public class TSResponse { ...@@ -250,42 +253,38 @@ public class TSResponse {
} }
} }
private boolean isSet(int position) {
return failureInfo[position];
}
public String getFailureCodeAsText() { public String getFailureCodeAsText() {
if (failureInfo == -1) { if (failureInfo == null) {
return null; return "";
} }
switch (failureInfo) { try {
if (isSet(BAD_ALG))
case BAD_ALG: return "Unrecognized or unsupported algorithm identifier.";
return "Unrecognized or unsupported alrorithm identifier."; if (isSet(BAD_REQUEST))
return "The requested transaction is not permitted or " +
case BAD_REQUEST: "supported.";
return "The requested transaction is not permitted or supported."; if (isSet(BAD_DATA_FORMAT))
return "The data submitted has the wrong format.";
case BAD_DATA_FORMAT: if (isSet(TIME_NOT_AVAILABLE))
return "The data submitted has the wrong format."; return "The TSA's time source is not available.";
if (isSet(UNACCEPTED_POLICY))
case TIME_NOT_AVAILABLE: return "The requested TSA policy is not supported by the TSA.";
return "The TSA's time source is not available."; if (isSet(UNACCEPTED_EXTENSION))
return "The requested extension is not supported by the TSA.";
case UNACCEPTED_POLICY: if (isSet(ADD_INFO_NOT_AVAILABLE))
return "The requested TSA policy is not supported by the TSA."; return "The additional information requested could not be " +
"understood or is not available.";
case UNACCEPTED_EXTENSION: if (isSet(SYSTEM_FAILURE))
return "The requested extension is not supported by the TSA."; return "The request cannot be handled due to system failure.";
} catch (ArrayIndexOutOfBoundsException ex) {}
case ADD_INFO_NOT_AVAILABLE:
return "The additional information requested could not be " + return ("unknown failure code");
"understood or is not available.";
case SYSTEM_FAILURE:
return "The request cannot be handled due to system failure.";
default:
return ("unknown status code " + status);
}
} }
/** /**
...@@ -297,6 +296,10 @@ public class TSResponse { ...@@ -297,6 +296,10 @@ public class TSResponse {
return tsToken; return tsToken;
} }
public TimestampToken getTimestampToken() {
return tstInfo;
}
/** /**
* Retrieve the ASN.1 BER encoded timestamp token returned by the TSA. * Retrieve the ASN.1 BER encoded timestamp token returned by the TSA.
* *
...@@ -323,29 +326,30 @@ public class TSResponse { ...@@ -323,29 +326,30 @@ public class TSResponse {
// Parse status // Parse status
DerValue status = derValue.data.getDerValue(); DerValue statusInfo = derValue.data.getDerValue();
// Parse status this.status = statusInfo.data.getInteger();
this.status = status.data.getInteger(); if (debug != null) {
if (DEBUG) { debug.println("timestamp response: status=" + this.status);
System.out.println("timestamp response: status=" + this.status);
} }
// Parse statusString, if present // Parse statusString, if present
if (status.data.available() > 0) { if (statusInfo.data.available() > 0) {
DerValue[] strings = status.data.getSequence(1); byte tag = (byte)statusInfo.data.peekByte();
statusString = new String[strings.length]; if (tag == DerValue.tag_SequenceOf) {
for (int i = 0; i < strings.length; i++) { DerValue[] strings = statusInfo.data.getSequence(1);
statusString[i] = strings[i].data.getUTF8String(); statusString = new String[strings.length];
for (int i = 0; i < strings.length; i++) {
statusString[i] = strings[i].getUTF8String();
if (debug != null) {
debug.println("timestamp response: statusString=" +
statusString[i]);
}
}
} }
} }
// Parse failInfo, if present // Parse failInfo, if present
if (status.data.available() > 0) { if (statusInfo.data.available() > 0) {
byte[] failInfo = status.data.getBitString(); this.failureInfo
int failureInfo = (new Byte(failInfo[0])).intValue(); = statusInfo.data.getUnalignedBitString().toBooleanArray();
if (failureInfo < 0 || failureInfo > 25 || failInfo.length != 1) {
throw new IOException("Bad encoding for timestamp response: " +
"unrecognized value for the failInfo element");
}
this.failureInfo = failureInfo;
} }
// Parse timeStampToken, if present // Parse timeStampToken, if present
...@@ -353,6 +357,7 @@ public class TSResponse { ...@@ -353,6 +357,7 @@ public class TSResponse {
DerValue timestampToken = derValue.data.getDerValue(); DerValue timestampToken = derValue.data.getDerValue();
encodedTsToken = timestampToken.toByteArray(); encodedTsToken = timestampToken.toByteArray();
tsToken = new PKCS7(encodedTsToken); tsToken = new PKCS7(encodedTsToken);
tstInfo = new TimestampToken(tsToken.getContentInfo().getData());
} }
// Check the format of the timestamp response // Check the format of the timestamp response
......
...@@ -1277,11 +1277,10 @@ public class JarSigner { ...@@ -1277,11 +1277,10 @@ public class JarSigner {
System.out.println(rb.getString("TSA.location.") + tsaUrl); System.out.println(rb.getString("TSA.location.") + tsaUrl);
} }
if (tsaCert != null) { if (tsaCert != null) {
String certUrl = URI tsaURI = TimestampedSigner.getTimestampingURI(tsaCert);
TimestampedSigner.getTimestampingUrl(tsaCert); if (tsaURI != null) {
if (certUrl != null) {
System.out.println(rb.getString("TSA.location.") + System.out.println(rb.getString("TSA.location.") +
certUrl); tsaURI);
} }
System.out.println(rb.getString("TSA.certificate.") + System.out.println(rb.getString("TSA.certificate.") +
printCert("", tsaCert, false, 0, false)); printCert("", tsaCert, false, 0, false));
......
...@@ -25,22 +25,14 @@ ...@@ -25,22 +25,14 @@
package sun.security.tools; package sun.security.tools;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger;
import java.net.URI; import java.net.URI;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.SecureRandom;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.List;
import com.sun.jarsigner.*; import com.sun.jarsigner.*;
import java.util.Arrays; import sun.security.pkcs.PKCS7;
import sun.security.pkcs.*;
import sun.security.timestamp.*;
import sun.security.util.*; import sun.security.util.*;
import sun.security.x509.*; import sun.security.x509.*;
...@@ -56,36 +48,12 @@ import sun.security.x509.*; ...@@ -56,36 +48,12 @@ import sun.security.x509.*;
public final class TimestampedSigner extends ContentSigner { public final class TimestampedSigner extends ContentSigner {
/*
* Random number generator for creating nonce values
*/
private static final SecureRandom RANDOM;
static {
SecureRandom tmp = null;
try {
tmp = SecureRandom.getInstance("SHA1PRNG");
} catch (NoSuchAlgorithmException e) {
// should not happen
}
RANDOM = tmp;
}
/* /*
* Object identifier for the subject information access X.509 certificate * Object identifier for the subject information access X.509 certificate
* extension. * extension.
*/ */
private static final String SUBJECT_INFO_ACCESS_OID = "1.3.6.1.5.5.7.1.11"; private static final String SUBJECT_INFO_ACCESS_OID = "1.3.6.1.5.5.7.1.11";
/*
* Object identifier for the timestamping key purpose.
*/
private static final String KP_TIMESTAMPING_OID = "1.3.6.1.5.5.7.3.8";
/*
* Object identifier for extendedKeyUsage extension
*/
private static final String EXTENDED_KEY_USAGE_OID = "2.5.29.37";
/* /*
* Object identifier for the timestamping access descriptors. * Object identifier for the timestamping access descriptors.
*/ */
...@@ -100,26 +68,6 @@ public final class TimestampedSigner extends ContentSigner { ...@@ -100,26 +68,6 @@ public final class TimestampedSigner extends ContentSigner {
AD_TIMESTAMPING_Id = tmp; AD_TIMESTAMPING_Id = tmp;
} }
/*
* Location of the TSA.
*/
private String tsaUrl = null;
/*
* TSA's X.509 certificate.
*/
private X509Certificate tsaCertificate = null;
/*
* Generates an SHA-1 hash value for the data to be timestamped.
*/
private MessageDigest messageDigest = null;
/*
* Parameters for the timestamping protocol.
*/
private boolean tsRequestCertificate = true;
/** /**
* Instantiates a content signer that supports timestamped signatures. * Instantiates a content signer that supports timestamped signatures.
*/ */
...@@ -134,7 +82,7 @@ public final class TimestampedSigner extends ContentSigner { ...@@ -134,7 +82,7 @@ public final class TimestampedSigner extends ContentSigner {
* and optionally the content that was signed, are packaged into a PKCS #7 * and optionally the content that was signed, are packaged into a PKCS #7
* signed data message. * signed data message.
* *
* @param parameters The non-null input parameters. * @param params The non-null input parameters.
* @param omitContent true if the content should be omitted from the * @param omitContent true if the content should be omitted from the
* signed data message. Otherwise the content is included. * signed data message. Otherwise the content is included.
* @param applyTimestamp true if the signature should be timestamped. * @param applyTimestamp true if the signature should be timestamped.
...@@ -151,98 +99,41 @@ public final class TimestampedSigner extends ContentSigner { ...@@ -151,98 +99,41 @@ public final class TimestampedSigner extends ContentSigner {
* @throws NullPointerException The exception is thrown if parameters is * @throws NullPointerException The exception is thrown if parameters is
* null. * null.
*/ */
public byte[] generateSignedData(ContentSignerParameters parameters, public byte[] generateSignedData(ContentSignerParameters params,
boolean omitContent, boolean applyTimestamp) boolean omitContent, boolean applyTimestamp)
throws NoSuchAlgorithmException, CertificateException, IOException { throws NoSuchAlgorithmException, CertificateException, IOException {
if (parameters == null) { if (params == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
// Parse the signature algorithm to extract the digest and key // Parse the signature algorithm to extract the digest
// algorithms. The expected format is: // algorithm. The expected format is:
// "<digest>with<encryption>" // "<digest>with<encryption>"
// or "<digest>with<encryption>and<mgf>" // or "<digest>with<encryption>and<mgf>"
String signatureAlgorithm = parameters.getSignatureAlgorithm(); String signatureAlgorithm = params.getSignatureAlgorithm();
String keyAlgorithm =
AlgorithmId.getEncAlgFromSigAlg(signatureAlgorithm);
String digestAlgorithm =
AlgorithmId.getDigAlgFromSigAlg(signatureAlgorithm);
AlgorithmId digestAlgorithmId = AlgorithmId.get(digestAlgorithm);
// Examine signer's certificate X509Certificate[] signerChain = params.getSignerCertificateChain();
X509Certificate[] signerCertificateChain = byte[] signature = params.getSignature();
parameters.getSignerCertificateChain();
Principal issuerName = signerCertificateChain[0].getIssuerDN();
if (!(issuerName instanceof X500Name)) {
// must extract the original encoded form of DN for subsequent
// name comparison checks (converting to a String and back to
// an encoded DN could cause the types of String attribute
// values to be changed)
X509CertInfo tbsCert = new
X509CertInfo(signerCertificateChain[0].getTBSCertificate());
issuerName = (Principal)
tbsCert.get(CertificateIssuerName.NAME + "." +
CertificateIssuerName.DN_NAME);
}
BigInteger serialNumber = signerCertificateChain[0].getSerialNumber();
// Include or exclude content // Include or exclude content
byte[] content = parameters.getContent(); byte[] content = (omitContent == true) ? null : params.getContent();
ContentInfo contentInfo;
if (omitContent) {
contentInfo = new ContentInfo(ContentInfo.DATA_OID, null);
} else {
contentInfo = new ContentInfo(content);
}
// Generate the timestamp token URI tsaURI = null;
byte[] signature = parameters.getSignature();
SignerInfo signerInfo = null;
if (applyTimestamp) { if (applyTimestamp) {
tsaURI = params.getTimestampingAuthority();
tsaCertificate = parameters.getTimestampingAuthorityCertificate(); if (tsaURI == null) {
URI tsaUri = parameters.getTimestampingAuthority();
if (tsaUri != null) {
tsaUrl = tsaUri.toString();
} else {
// Examine TSA cert // Examine TSA cert
String certUrl = getTimestampingUrl(tsaCertificate); tsaURI = getTimestampingURI(
if (certUrl == null) { params.getTimestampingAuthorityCertificate());
if (tsaURI == null) {
throw new CertificateException( throw new CertificateException(
"Subject Information Access extension not found"); "Subject Information Access extension not found");
} }
tsaUrl = certUrl;
} }
// Timestamp the signature
byte[] tsToken = generateTimestampToken(signature);
// Insert the timestamp token into the PKCS #7 signer info element
// (as an unsigned attribute)
PKCS9Attributes unsignedAttrs =
new PKCS9Attributes(new PKCS9Attribute[]{
new PKCS9Attribute(
PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_STR,
tsToken)});
signerInfo = new SignerInfo((X500Name)issuerName, serialNumber,
digestAlgorithmId, null, AlgorithmId.get(keyAlgorithm),
signature, unsignedAttrs);
} else {
signerInfo = new SignerInfo((X500Name)issuerName, serialNumber,
digestAlgorithmId, AlgorithmId.get(keyAlgorithm), signature);
} }
return PKCS7.generateSignedData(signature, signerChain, content,
SignerInfo[] signerInfos = {signerInfo}; params.getSignatureAlgorithm(), tsaURI);
AlgorithmId[] algorithms = {digestAlgorithmId};
// Create the PKCS #7 signed data message
PKCS7 p7 = new PKCS7(algorithms, contentInfo, signerCertificateChain,
null, signerInfos);
ByteArrayOutputStream p7out = new ByteArrayOutputStream();
p7.encodeSignedData(p7out);
return p7out.toByteArray();
} }
/** /**
...@@ -253,9 +144,9 @@ public final class TimestampedSigner extends ContentSigner { ...@@ -253,9 +144,9 @@ public final class TimestampedSigner extends ContentSigner {
* <tt>accessLocation</tt> field should contain an HTTP or HTTPS URL. * <tt>accessLocation</tt> field should contain an HTTP or HTTPS URL.
* *
* @param tsaCertificate An X.509 certificate for the TSA. * @param tsaCertificate An X.509 certificate for the TSA.
* @return An HTTP or HTTPS URL or null if none was found. * @return An HTTP or HTTPS URI or null if none was found.
*/ */
public static String getTimestampingUrl(X509Certificate tsaCertificate) { public static URI getTimestampingURI(X509Certificate tsaCertificate) {
if (tsaCertificate == null) { if (tsaCertificate == null) {
return null; return null;
...@@ -282,7 +173,7 @@ public final class TimestampedSigner extends ContentSigner { ...@@ -282,7 +173,7 @@ public final class TimestampedSigner extends ContentSigner {
uri = (URIName) location.getName(); uri = (URIName) location.getName();
if (uri.getScheme().equalsIgnoreCase("http") || if (uri.getScheme().equalsIgnoreCase("http") ||
uri.getScheme().equalsIgnoreCase("https")) { uri.getScheme().equalsIgnoreCase("https")) {
return uri.getName(); return uri.getURI();
} }
} }
} }
...@@ -292,97 +183,4 @@ public final class TimestampedSigner extends ContentSigner { ...@@ -292,97 +183,4 @@ public final class TimestampedSigner extends ContentSigner {
} }
return null; return null;
} }
/*
* Returns a timestamp token from a TSA for the given content.
* Performs a basic check on the token to confirm that it has been signed
* by a certificate that is permitted to sign timestamps.
*
* @param toBeTimestamped The data to be timestamped.
* @throws IOException The exception is throw if an error occurs while
* communicating with the TSA.
* @throws CertificateException The exception is throw if the TSA's
* certificate is not permitted for timestamping.
*/
private byte[] generateTimestampToken(byte[] toBeTimestamped)
throws CertificateException, IOException {
// Generate hash value for the data to be timestamped
// SHA-1 is always used.
if (messageDigest == null) {
try {
messageDigest = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
// ignore
}
}
byte[] digest = messageDigest.digest(toBeTimestamped);
// Generate a timestamp
TSRequest tsQuery = new TSRequest(digest, "SHA-1");
// Generate a nonce
BigInteger nonce = null;
if (RANDOM != null) {
nonce = new BigInteger(64, RANDOM);
tsQuery.setNonce(nonce);
}
tsQuery.requestCertificate(tsRequestCertificate);
Timestamper tsa = new HttpTimestamper(tsaUrl); // use supplied TSA
TSResponse tsReply = tsa.generateTimestamp(tsQuery);
int status = tsReply.getStatusCode();
// Handle TSP error
if (status != 0 && status != 1) {
int failureCode = tsReply.getFailureCode();
if (failureCode == -1) {
throw new IOException("Error generating timestamp: " +
tsReply.getStatusCodeAsText());
} else {
throw new IOException("Error generating timestamp: " +
tsReply.getStatusCodeAsText() + " " +
tsReply.getFailureCodeAsText());
}
}
PKCS7 tsToken = tsReply.getToken();
TimestampToken tst = new TimestampToken(tsToken.getContentInfo().getData());
if (!tst.getHashAlgorithm().equals(
new AlgorithmId(new ObjectIdentifier("1.3.14.3.2.26")))) {
throw new IOException("Digest algorithm not SHA-1 in timestamp token");
}
if (!Arrays.equals(tst.getHashedMessage(), digest)) {
throw new IOException("Digest octets changed in timestamp token");
}
BigInteger replyNonce = tst.getNonce();
if (replyNonce == null && nonce != null) {
throw new IOException("Nonce missing in timestamp token");
}
if (replyNonce != null && !replyNonce.equals(nonce)) {
throw new IOException("Nonce changed in timestamp token");
}
// Examine the TSA's certificate (if present)
for (SignerInfo si: tsToken.getSignerInfos()) {
X509Certificate cert = si.getCertificate(tsToken);
if (cert == null) {
// Error, we've already set tsRequestCertificate = true
throw new CertificateException(
"Certificate not included in timestamp token");
} else {
if (!cert.getCriticalExtensionOIDs().contains(
EXTENDED_KEY_USAGE_OID)) {
throw new CertificateException(
"Certificate is not valid for timestamping");
}
List<String> keyPurposes = cert.getExtendedKeyUsage();
if (keyPurposes == null ||
! keyPurposes.contains(KP_TIMESTAMPING_OID)) {
throw new CertificateException(
"Certificate is not valid for timestamping");
}
}
}
return tsReply.getEncodedToken();
}
} }
/* /*
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -80,6 +80,7 @@ public class Debug { ...@@ -80,6 +80,7 @@ public class Debug {
System.err.println("policy loading and granting"); System.err.println("policy loading and granting");
System.err.println("provider security provider debugging"); System.err.println("provider security provider debugging");
System.err.println("scl permissions SecureClassLoader assigns"); System.err.println("scl permissions SecureClassLoader assigns");
System.err.println("ts timestamping");
System.err.println(); System.err.println();
System.err.println("The following can be used with access:"); System.err.println("The following can be used with access:");
System.err.println(); System.err.println();
......
...@@ -35,7 +35,6 @@ import java.util.*; ...@@ -35,7 +35,6 @@ import java.util.*;
import java.util.jar.*; import java.util.jar.*;
import sun.security.pkcs.*; import sun.security.pkcs.*;
import sun.security.timestamp.TimestampToken;
import sun.misc.BASE64Decoder; import sun.misc.BASE64Decoder;
import sun.security.jca.Providers; import sun.security.jca.Providers;
...@@ -485,7 +484,7 @@ public class SignatureFileVerifier { ...@@ -485,7 +484,7 @@ public class SignatureFileVerifier {
signers = new ArrayList<CodeSigner>(); signers = new ArrayList<CodeSigner>();
} }
// Append the new code signer // Append the new code signer
signers.add(new CodeSigner(certChain, getTimestamp(info))); signers.add(new CodeSigner(certChain, info.getTimestamp()));
if (debug != null) { if (debug != null) {
debug.println("Signature Block Certificate: " + debug.println("Signature Block Certificate: " +
...@@ -500,62 +499,6 @@ public class SignatureFileVerifier { ...@@ -500,62 +499,6 @@ public class SignatureFileVerifier {
} }
} }
/*
* Examines a signature timestamp token to generate a timestamp object.
*
* Examines the signer's unsigned attributes for a
* <tt>signatureTimestampToken</tt> attribute. If present,
* then it is parsed to extract the date and time at which the
* timestamp was generated.
*
* @param info A signer information element of a PKCS 7 block.
*
* @return A timestamp token or null if none is present.
* @throws IOException if an error is encountered while parsing the
* PKCS7 data.
* @throws NoSuchAlgorithmException if an error is encountered while
* verifying the PKCS7 object.
* @throws SignatureException if an error is encountered while
* verifying the PKCS7 object.
* @throws CertificateException if an error is encountered while generating
* the TSA's certpath.
*/
private Timestamp getTimestamp(SignerInfo info)
throws IOException, NoSuchAlgorithmException, SignatureException,
CertificateException {
Timestamp timestamp = null;
// Extract the signer's unsigned attributes
PKCS9Attributes unsignedAttrs = info.getUnauthenticatedAttributes();
if (unsignedAttrs != null) {
PKCS9Attribute timestampTokenAttr =
unsignedAttrs.getAttribute("signatureTimestampToken");
if (timestampTokenAttr != null) {
PKCS7 timestampToken =
new PKCS7((byte[])timestampTokenAttr.getValue());
// Extract the content (an encoded timestamp token info)
byte[] encodedTimestampTokenInfo =
timestampToken.getContentInfo().getData();
// Extract the signer (the Timestamping Authority)
// while verifying the content
SignerInfo[] tsa =
timestampToken.verify(encodedTimestampTokenInfo);
// Expect only one signer
ArrayList<X509Certificate> chain =
tsa[0].getCertificateChain(timestampToken);
CertPath tsaChain = certificateFactory.generateCertPath(chain);
// Create a timestamp token info object
TimestampToken timestampTokenInfo =
new TimestampToken(encodedTimestampTokenInfo);
// Create a timestamp object
timestamp =
new Timestamp(timestampTokenInfo.getDate(), tsaChain);
}
}
return timestamp;
}
// for the toHex function // for the toHex function
private static final char[] hexc = private static final char[] hexc =
{'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
......
/*
* Copyright (c) 2011, 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.
*
* 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.
*/
/* @test
* @bug 7084030
* @summary Tests that DatagramSocket.getLocalAddress returns the right local
* address after connect/disconnect.
*/
import java.net.*;
public class ChangingAddress {
static void check(DatagramSocket ds, InetAddress expected) {
InetAddress actual = ds.getLocalAddress();
if (!expected.equals(actual)) {
throw new RuntimeException("Expected:"+expected+" Actual"+
actual);
}
}
public static void main(String[] args) throws Exception {
InetAddress lh = InetAddress.getLocalHost();
SocketAddress remote = new InetSocketAddress(lh, 1234);
InetAddress wildcard = InetAddress.getByAddress
("localhost", new byte[]{0,0,0,0});
try (DatagramSocket ds = new DatagramSocket()) {
check(ds, wildcard);
ds.connect(remote);
check(ds, lh);
ds.disconnect();
check(ds, wildcard);
}
}
}
/*
* Copyright (c) 2011, 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.
*
* 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.
*/
/*
* @test
* @bug 5020931
* @summary Unit test for Collections.checkedQueue
*/
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Iterator;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
public class CheckedQueue {
static int status = 0;
public static void main(String[] args) throws Exception {
new CheckedQueue();
}
public CheckedQueue() throws Exception {
run();
}
private void run() throws Exception {
Method[] methods = this.getClass().getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
String methodName = method.getName();
if (methodName.startsWith("test")) {
try {
Object obj = method.invoke(this, new Object[0]);
} catch(Exception e) {
throw new Exception(this.getClass().getName() + "." +
methodName + " test failed, test exception "
+ "follows\n" + e.getCause());
}
}
}
}
/**
* This test adds items to a queue.
*/
private void test00() {
int arrayLength = 10;
ArrayBlockingQueue<String> abq = new ArrayBlockingQueue(arrayLength);
for (int i = 0; i < arrayLength; i++) {
abq.add(new String(Integer.toString(i)));
}
}
/**
* This test tests the CheckedQueue.add method. It creates a queue of
* {@code String}s gets the checked queue, and attempt to add an Integer to
* the checked queue.
*/
private void test01() throws Exception {
int arrayLength = 10;
ArrayBlockingQueue<String> abq = new ArrayBlockingQueue(arrayLength + 1);
for (int i = 0; i < arrayLength; i++) {
abq.add(new String(Integer.toString(i)));
}
Queue q = Collections.checkedQueue(abq, String.class);
try {
q.add(new Integer(0));
throw new Exception(this.getClass().getName() + "." + "test01 test"
+ " failed, should throw ClassCastException.");
} catch(ClassCastException cce) {
// Do nothing.
}
}
/**
* This test tests the CheckedQueue.add method. It creates a queue of one
* {@code String}, gets the checked queue, and attempt to add an Integer to
* the checked queue.
*/
private void test02() throws Exception {
ArrayBlockingQueue<String> abq = new ArrayBlockingQueue(1);
Queue q = Collections.checkedQueue(abq, String.class);
try {
q.add(new Integer(0));
throw new Exception(this.getClass().getName() + "." + "test02 test"
+ " failed, should throw ClassCastException.");
} catch(ClassCastException e) {
// Do nothing.
}
}
/**
* This test tests the Collections.checkedQueue method call for nulls in
* each and both of the parameters.
*/
private void test03() throws Exception {
ArrayBlockingQueue<String> abq = new ArrayBlockingQueue(1);
Queue q;
try {
q = Collections.checkedQueue(null, String.class);
throw new Exception(this.getClass().getName() + "." + "test03 test"
+ " failed, should throw NullPointerException.");
} catch(NullPointerException npe) {
// Do nothing
}
try {
q = Collections.checkedQueue(abq, null);
throw new Exception(this.getClass().getName() + "." + "test03 test"
+ " failed, should throw NullPointerException.");
} catch(Exception e) {
// Do nothing
}
try {
q = Collections.checkedQueue(null, null);
throw new Exception(this.getClass().getName() + "." + "test03 test"
+ " failed, should throw NullPointerException.");
} catch(Exception e) {
// Do nothing
}
}
/**
* This test tests the CheckedQueue.offer method.
*/
private void test04() throws Exception {
ArrayBlockingQueue<String> abq = new ArrayBlockingQueue(1);
Queue q = Collections.checkedQueue(abq, String.class);
try {
q.offer(null);
throw new Exception(this.getClass().getName() + "." + "test04 test"
+ " failed, should throw NullPointerException.");
} catch (NullPointerException npe) {
// Do nothing
}
try {
q.offer(new Integer(0));
throw new Exception(this.getClass().getName() + "." + "test04 test"
+ " failed, should throw ClassCastException.");
} catch (ClassCastException cce) {
// Do nothing
}
q.offer(new String("0"));
try {
q.offer(new String("1"));
throw new Exception(this.getClass().getName() + "." + "test04 test"
+ " failed, should throw IllegalStateException.");
} catch(IllegalStateException ise) {
// Do nothing
}
}
private void test05() {
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册