mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-09 22:48:41 +00:00
Merge
This commit is contained in:
commit
75c70b068f
@ -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.
|
||||
* Any attempt to insert an element of the wrong type will result in
|
||||
|
||||
@ -27,6 +27,7 @@ package sun.security.pkcs;
|
||||
|
||||
import java.io.*;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URI;
|
||||
import java.util.*;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
@ -35,6 +36,7 @@ import java.security.cert.CRLException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.*;
|
||||
|
||||
import sun.security.timestamp.*;
|
||||
import sun.security.util.*;
|
||||
import sun.security.x509.AlgorithmId;
|
||||
import sun.security.x509.CertificateIssuerName;
|
||||
@ -68,6 +70,30 @@ public class PKCS7 {
|
||||
|
||||
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
|
||||
* encoded bytes from the InputStream.
|
||||
@ -733,4 +759,164 @@ public class PKCS7 {
|
||||
public boolean isOldStyle() {
|
||||
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;
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
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.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import sun.security.timestamp.TimestampToken;
|
||||
import sun.security.util.*;
|
||||
import sun.security.x509.AlgorithmId;
|
||||
import sun.security.x509.X500Name;
|
||||
@ -51,6 +55,8 @@ public class SignerInfo implements DerEncoder {
|
||||
AlgorithmId digestAlgorithmId;
|
||||
AlgorithmId digestEncryptionAlgorithmId;
|
||||
byte[] encryptedDigest;
|
||||
Timestamp timestamp;
|
||||
private boolean hasTimestamp = true;
|
||||
|
||||
PKCS9Attributes authenticatedAttributes;
|
||||
PKCS9Attributes unauthenticatedAttributes;
|
||||
@ -442,6 +448,62 @@ public class SignerInfo implements DerEncoder {
|
||||
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() {
|
||||
HexDumpEncoder hexDump = new HexDumpEncoder();
|
||||
|
||||
@ -467,5 +529,4 @@ public class SignerInfo implements DerEncoder {
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -28,13 +28,13 @@ package sun.security.timestamp;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import sun.misc.IOUtils;
|
||||
import sun.security.util.Debug;
|
||||
|
||||
/**
|
||||
* A timestamper that communicates with a Timestamping Authority (TSA)
|
||||
@ -58,20 +58,23 @@ public class HttpTimestamper implements Timestamper {
|
||||
private static final String TS_REPLY_MIME_TYPE =
|
||||
"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.
|
||||
*
|
||||
* @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) {
|
||||
this.tsaUrl = tsaUrl;
|
||||
public HttpTimestamper(URI tsaURI) {
|
||||
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 {
|
||||
public TSResponse generateTimestamp(TSRequest tsQuery) throws IOException {
|
||||
|
||||
HttpURLConnection connection =
|
||||
(HttpURLConnection) new URL(tsaUrl).openConnection();
|
||||
(HttpURLConnection) tsaURI.toURL().openConnection();
|
||||
connection.setDoOutput(true);
|
||||
connection.setUseCaches(false); // ignore cache
|
||||
connection.setRequestProperty("Content-Type", TS_QUERY_MIME_TYPE);
|
||||
@ -93,15 +96,15 @@ public class HttpTimestamper implements Timestamper {
|
||||
// Avoids the "hang" when a proxy is required but none has been set.
|
||||
connection.setConnectTimeout(CONNECT_TIMEOUT);
|
||||
|
||||
if (DEBUG) {
|
||||
if (debug != null) {
|
||||
Set<Map.Entry<String, List<String>>> headers =
|
||||
connection.getRequestProperties().entrySet();
|
||||
System.out.println(connection.getRequestMethod() + " " + tsaUrl +
|
||||
connection.getRequestProperties().entrySet();
|
||||
debug.println(connection.getRequestMethod() + " " + tsaURI +
|
||||
" HTTP/1.1");
|
||||
for (Map.Entry<String, List<String>> entry : headers) {
|
||||
System.out.println(" " + entry);
|
||||
for (Map.Entry<String, List<String>> e : headers) {
|
||||
debug.println(" " + e);
|
||||
}
|
||||
System.out.println();
|
||||
debug.println();
|
||||
}
|
||||
connection.connect(); // No HTTP authentication is performed
|
||||
|
||||
@ -112,8 +115,8 @@ public class HttpTimestamper implements Timestamper {
|
||||
byte[] request = tsQuery.encode();
|
||||
output.write(request, 0, request.length);
|
||||
output.flush();
|
||||
if (DEBUG) {
|
||||
System.out.println("sent timestamp query (length=" +
|
||||
if (debug != null) {
|
||||
debug.println("sent timestamp query (length=" +
|
||||
request.length + ")");
|
||||
}
|
||||
} finally {
|
||||
@ -127,17 +130,17 @@ public class HttpTimestamper implements Timestamper {
|
||||
byte[] replyBuffer = null;
|
||||
try {
|
||||
input = new BufferedInputStream(connection.getInputStream());
|
||||
if (DEBUG) {
|
||||
if (debug != null) {
|
||||
String header = connection.getHeaderField(0);
|
||||
System.out.println(header);
|
||||
debug.println(header);
|
||||
int i = 1;
|
||||
while ((header = connection.getHeaderField(i)) != null) {
|
||||
String key = connection.getHeaderFieldKey(i);
|
||||
System.out.println(" " + ((key==null) ? "" : key + ": ") +
|
||||
debug.println(" " + ((key==null) ? "" : key + ": ") +
|
||||
header);
|
||||
i++;
|
||||
}
|
||||
System.out.println();
|
||||
debug.println();
|
||||
}
|
||||
verifyMimeType(connection.getContentType());
|
||||
|
||||
@ -145,8 +148,8 @@ public class HttpTimestamper implements Timestamper {
|
||||
int contentLength = connection.getContentLength();
|
||||
replyBuffer = IOUtils.readFully(input, contentLength, false);
|
||||
|
||||
if (DEBUG) {
|
||||
System.out.println("received timestamp response (length=" +
|
||||
if (debug != null) {
|
||||
debug.println("received timestamp response (length=" +
|
||||
total + ")");
|
||||
}
|
||||
} finally {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,10 +27,13 @@ package sun.security.timestamp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.X509Extension;
|
||||
import sun.security.util.DerValue;
|
||||
import sun.security.util.DerOutputStream;
|
||||
import sun.security.util.ObjectIdentifier;
|
||||
import sun.security.x509.AlgorithmId;
|
||||
|
||||
/**
|
||||
* This class provides a timestamp request, as defined in
|
||||
@ -64,24 +67,9 @@ import sun.security.util.ObjectIdentifier;
|
||||
|
||||
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 ObjectIdentifier hashAlgorithmId = null;
|
||||
private AlgorithmId hashAlgorithmId = null;
|
||||
|
||||
private byte[] hashValue;
|
||||
|
||||
@ -94,30 +82,21 @@ public class TSRequest {
|
||||
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 hashAlgorithm The name of the hash algorithm.
|
||||
* @param toBeTimeStamped The data to be timestamped.
|
||||
* @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
|
||||
if ("MD5".equalsIgnoreCase(hashAlgorithm)) {
|
||||
hashAlgorithmId = MD5_OID;
|
||||
// Check that the hash value matches the hash algorithm
|
||||
assert hashValue.length == 16;
|
||||
this.hashAlgorithmId = AlgorithmId.get(messageDigest.getAlgorithm());
|
||||
this.hashValue = messageDigest.digest(toBeTimeStamped);
|
||||
}
|
||||
|
||||
} 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;
|
||||
|
||||
}
|
||||
// Clone the hash value
|
||||
this.hashValue = new byte[hashValue.length];
|
||||
System.arraycopy(hashValue, 0, this.hashValue, 0, hashValue.length);
|
||||
public byte[] getHashedMessage() {
|
||||
return hashValue.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,9 +155,7 @@ public class TSRequest {
|
||||
|
||||
// encode messageImprint
|
||||
DerOutputStream messageImprint = new DerOutputStream();
|
||||
DerOutputStream hashAlgorithm = new DerOutputStream();
|
||||
hashAlgorithm.putOID(hashAlgorithmId);
|
||||
messageImprint.write(DerValue.tag_Sequence, hashAlgorithm);
|
||||
hashAlgorithmId.encode(messageImprint);
|
||||
messageImprint.putOctetString(hashValue);
|
||||
request.write(DerValue.tag_Sequence, messageImprint);
|
||||
|
||||
|
||||
@ -27,6 +27,7 @@ package sun.security.timestamp;
|
||||
|
||||
import java.io.IOException;
|
||||
import sun.security.pkcs.PKCS7;
|
||||
import sun.security.util.Debug;
|
||||
import sun.security.util.DerValue;
|
||||
|
||||
/**
|
||||
@ -175,18 +176,20 @@ public class TSResponse {
|
||||
*/
|
||||
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 String[] statusString = null;
|
||||
|
||||
private int failureInfo = -1;
|
||||
private boolean[] failureInfo = null;
|
||||
|
||||
private byte[] encodedTsToken = null;
|
||||
|
||||
private PKCS7 tsToken = null;
|
||||
|
||||
private TimestampToken tstInfo;
|
||||
|
||||
/**
|
||||
* Constructs an object to store the response to a timestamp request.
|
||||
*
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -250,42 +253,38 @@ public class TSResponse {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSet(int position) {
|
||||
return failureInfo[position];
|
||||
}
|
||||
|
||||
public String getFailureCodeAsText() {
|
||||
|
||||
if (failureInfo == -1) {
|
||||
return null;
|
||||
if (failureInfo == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
switch (failureInfo) {
|
||||
try {
|
||||
if (isSet(BAD_ALG))
|
||||
return "Unrecognized or unsupported algorithm identifier.";
|
||||
if (isSet(BAD_REQUEST))
|
||||
return "The requested transaction is not permitted or " +
|
||||
"supported.";
|
||||
if (isSet(BAD_DATA_FORMAT))
|
||||
return "The data submitted has the wrong format.";
|
||||
if (isSet(TIME_NOT_AVAILABLE))
|
||||
return "The TSA's time source is not available.";
|
||||
if (isSet(UNACCEPTED_POLICY))
|
||||
return "The requested TSA policy is not supported by the TSA.";
|
||||
if (isSet(UNACCEPTED_EXTENSION))
|
||||
return "The requested extension is not supported by the TSA.";
|
||||
if (isSet(ADD_INFO_NOT_AVAILABLE))
|
||||
return "The additional information requested could not be " +
|
||||
"understood or is not available.";
|
||||
if (isSet(SYSTEM_FAILURE))
|
||||
return "The request cannot be handled due to system failure.";
|
||||
} catch (ArrayIndexOutOfBoundsException ex) {}
|
||||
|
||||
case BAD_ALG:
|
||||
return "Unrecognized or unsupported alrorithm identifier.";
|
||||
|
||||
case BAD_REQUEST:
|
||||
return "The requested transaction is not permitted or supported.";
|
||||
|
||||
case BAD_DATA_FORMAT:
|
||||
return "The data submitted has the wrong format.";
|
||||
|
||||
case TIME_NOT_AVAILABLE:
|
||||
return "The TSA's time source is not available.";
|
||||
|
||||
case UNACCEPTED_POLICY:
|
||||
return "The requested TSA policy is not supported by the TSA.";
|
||||
|
||||
case UNACCEPTED_EXTENSION:
|
||||
return "The requested extension is not supported by the TSA.";
|
||||
|
||||
case ADD_INFO_NOT_AVAILABLE:
|
||||
return "The additional information requested could not be " +
|
||||
"understood or is not available.";
|
||||
|
||||
case SYSTEM_FAILURE:
|
||||
return "The request cannot be handled due to system failure.";
|
||||
|
||||
default:
|
||||
return ("unknown status code " + status);
|
||||
}
|
||||
return ("unknown failure code");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -297,6 +296,10 @@ public class TSResponse {
|
||||
return tsToken;
|
||||
}
|
||||
|
||||
public TimestampToken getTimestampToken() {
|
||||
return tstInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the ASN.1 BER encoded timestamp token returned by the TSA.
|
||||
*
|
||||
@ -323,29 +326,30 @@ public class TSResponse {
|
||||
|
||||
// Parse status
|
||||
|
||||
DerValue status = derValue.data.getDerValue();
|
||||
// Parse status
|
||||
this.status = status.data.getInteger();
|
||||
if (DEBUG) {
|
||||
System.out.println("timestamp response: status=" + this.status);
|
||||
DerValue statusInfo = derValue.data.getDerValue();
|
||||
this.status = statusInfo.data.getInteger();
|
||||
if (debug != null) {
|
||||
debug.println("timestamp response: status=" + this.status);
|
||||
}
|
||||
// Parse statusString, if present
|
||||
if (status.data.available() > 0) {
|
||||
DerValue[] strings = status.data.getSequence(1);
|
||||
statusString = new String[strings.length];
|
||||
for (int i = 0; i < strings.length; i++) {
|
||||
statusString[i] = strings[i].data.getUTF8String();
|
||||
if (statusInfo.data.available() > 0) {
|
||||
byte tag = (byte)statusInfo.data.peekByte();
|
||||
if (tag == DerValue.tag_SequenceOf) {
|
||||
DerValue[] strings = statusInfo.data.getSequence(1);
|
||||
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
|
||||
if (status.data.available() > 0) {
|
||||
byte[] failInfo = status.data.getBitString();
|
||||
int failureInfo = (new Byte(failInfo[0])).intValue();
|
||||
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;
|
||||
if (statusInfo.data.available() > 0) {
|
||||
this.failureInfo
|
||||
= statusInfo.data.getUnalignedBitString().toBooleanArray();
|
||||
}
|
||||
|
||||
// Parse timeStampToken, if present
|
||||
@ -353,6 +357,7 @@ public class TSResponse {
|
||||
DerValue timestampToken = derValue.data.getDerValue();
|
||||
encodedTsToken = timestampToken.toByteArray();
|
||||
tsToken = new PKCS7(encodedTsToken);
|
||||
tstInfo = new TimestampToken(tsToken.getContentInfo().getData());
|
||||
}
|
||||
|
||||
// Check the format of the timestamp response
|
||||
|
||||
@ -1277,11 +1277,10 @@ public class JarSigner {
|
||||
System.out.println(rb.getString("TSA.location.") + tsaUrl);
|
||||
}
|
||||
if (tsaCert != null) {
|
||||
String certUrl =
|
||||
TimestampedSigner.getTimestampingUrl(tsaCert);
|
||||
if (certUrl != null) {
|
||||
URI tsaURI = TimestampedSigner.getTimestampingURI(tsaCert);
|
||||
if (tsaURI != null) {
|
||||
System.out.println(rb.getString("TSA.location.") +
|
||||
certUrl);
|
||||
tsaURI);
|
||||
}
|
||||
System.out.println(rb.getString("TSA.certificate.") +
|
||||
printCert("", tsaCert, false, 0, false));
|
||||
|
||||
@ -25,22 +25,14 @@
|
||||
|
||||
package sun.security.tools;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URI;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Principal;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.jarsigner.*;
|
||||
import java.util.Arrays;
|
||||
import sun.security.pkcs.*;
|
||||
import sun.security.timestamp.*;
|
||||
import sun.security.pkcs.PKCS7;
|
||||
import sun.security.util.*;
|
||||
import sun.security.x509.*;
|
||||
|
||||
@ -56,36 +48,12 @@ import sun.security.x509.*;
|
||||
|
||||
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
|
||||
* extension.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
@ -100,26 +68,6 @@ public final class TimestampedSigner extends ContentSigner {
|
||||
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.
|
||||
*/
|
||||
@ -134,7 +82,7 @@ public final class TimestampedSigner extends ContentSigner {
|
||||
* and optionally the content that was signed, are packaged into a PKCS #7
|
||||
* 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
|
||||
* signed data message. Otherwise the content is included.
|
||||
* @param applyTimestamp true if the signature should be timestamped.
|
||||
@ -151,98 +99,41 @@ public final class TimestampedSigner extends ContentSigner {
|
||||
* @throws NullPointerException The exception is thrown if parameters is
|
||||
* null.
|
||||
*/
|
||||
public byte[] generateSignedData(ContentSignerParameters parameters,
|
||||
public byte[] generateSignedData(ContentSignerParameters params,
|
||||
boolean omitContent, boolean applyTimestamp)
|
||||
throws NoSuchAlgorithmException, CertificateException, IOException {
|
||||
|
||||
if (parameters == null) {
|
||||
if (params == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
// Parse the signature algorithm to extract the digest and key
|
||||
// algorithms. The expected format is:
|
||||
// Parse the signature algorithm to extract the digest
|
||||
// algorithm. The expected format is:
|
||||
// "<digest>with<encryption>"
|
||||
// or "<digest>with<encryption>and<mgf>"
|
||||
String signatureAlgorithm = parameters.getSignatureAlgorithm();
|
||||
String keyAlgorithm =
|
||||
AlgorithmId.getEncAlgFromSigAlg(signatureAlgorithm);
|
||||
String digestAlgorithm =
|
||||
AlgorithmId.getDigAlgFromSigAlg(signatureAlgorithm);
|
||||
AlgorithmId digestAlgorithmId = AlgorithmId.get(digestAlgorithm);
|
||||
String signatureAlgorithm = params.getSignatureAlgorithm();
|
||||
|
||||
// Examine signer's certificate
|
||||
X509Certificate[] signerCertificateChain =
|
||||
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();
|
||||
X509Certificate[] signerChain = params.getSignerCertificateChain();
|
||||
byte[] signature = params.getSignature();
|
||||
|
||||
// Include or exclude content
|
||||
byte[] content = parameters.getContent();
|
||||
ContentInfo contentInfo;
|
||||
if (omitContent) {
|
||||
contentInfo = new ContentInfo(ContentInfo.DATA_OID, null);
|
||||
} else {
|
||||
contentInfo = new ContentInfo(content);
|
||||
}
|
||||
byte[] content = (omitContent == true) ? null : params.getContent();
|
||||
|
||||
// Generate the timestamp token
|
||||
byte[] signature = parameters.getSignature();
|
||||
SignerInfo signerInfo = null;
|
||||
URI tsaURI = null;
|
||||
if (applyTimestamp) {
|
||||
|
||||
tsaCertificate = parameters.getTimestampingAuthorityCertificate();
|
||||
URI tsaUri = parameters.getTimestampingAuthority();
|
||||
if (tsaUri != null) {
|
||||
tsaUrl = tsaUri.toString();
|
||||
} else {
|
||||
tsaURI = params.getTimestampingAuthority();
|
||||
if (tsaURI == null) {
|
||||
// Examine TSA cert
|
||||
String certUrl = getTimestampingUrl(tsaCertificate);
|
||||
if (certUrl == null) {
|
||||
tsaURI = getTimestampingURI(
|
||||
params.getTimestampingAuthorityCertificate());
|
||||
if (tsaURI == null) {
|
||||
throw new CertificateException(
|
||||
"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);
|
||||
}
|
||||
|
||||
SignerInfo[] signerInfos = {signerInfo};
|
||||
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();
|
||||
return PKCS7.generateSignedData(signature, signerChain, content,
|
||||
params.getSignatureAlgorithm(), tsaURI);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -253,9 +144,9 @@ public final class TimestampedSigner extends ContentSigner {
|
||||
* <tt>accessLocation</tt> field should contain an HTTP or HTTPS URL.
|
||||
*
|
||||
* @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) {
|
||||
return null;
|
||||
@ -282,7 +173,7 @@ public final class TimestampedSigner extends ContentSigner {
|
||||
uri = (URIName) location.getName();
|
||||
if (uri.getScheme().equalsIgnoreCase("http") ||
|
||||
uri.getScheme().equalsIgnoreCase("https")) {
|
||||
return uri.getName();
|
||||
return uri.getURI();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -292,97 +183,4 @@ public final class TimestampedSigner extends ContentSigner {
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -80,6 +80,7 @@ public class Debug {
|
||||
System.err.println("policy loading and granting");
|
||||
System.err.println("provider security provider debugging");
|
||||
System.err.println("scl permissions SecureClassLoader assigns");
|
||||
System.err.println("ts timestamping");
|
||||
System.err.println();
|
||||
System.err.println("The following can be used with access:");
|
||||
System.err.println();
|
||||
|
||||
@ -35,7 +35,6 @@ import java.util.*;
|
||||
import java.util.jar.*;
|
||||
|
||||
import sun.security.pkcs.*;
|
||||
import sun.security.timestamp.TimestampToken;
|
||||
import sun.misc.BASE64Decoder;
|
||||
|
||||
import sun.security.jca.Providers;
|
||||
@ -485,7 +484,7 @@ public class SignatureFileVerifier {
|
||||
signers = new ArrayList<CodeSigner>();
|
||||
}
|
||||
// Append the new code signer
|
||||
signers.add(new CodeSigner(certChain, getTimestamp(info)));
|
||||
signers.add(new CodeSigner(certChain, info.getTimestamp()));
|
||||
|
||||
if (debug != null) {
|
||||
debug.println("Signature Block Certificate: " +
|
||||
@ -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
|
||||
private static final char[] hexc =
|
||||
{'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
|
||||
|
||||
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
190
jdk/test/java/util/Collections/CheckedQueue.java
Normal file
190
jdk/test/java/util/Collections/CheckedQueue.java
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* 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() {
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user