1 /* 2 * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.timestamp; 27 28 import java.io.IOException; 29 import java.math.BigInteger; 30 import java.security.cert.X509Extension; 31 import sun.security.util.DerValue; 32 import sun.security.util.DerOutputStream; 33 import sun.security.util.ObjectIdentifier; 34 35 /** 36 * This class provides a timestamp request, as defined in 37 * <a href="http://www.ietf.org/rfc/rfc3161.txt">RFC 3161</a>. 38 * 39 * The TimeStampReq ASN.1 type has the following definition: 40 * <pre> 41 * 42 * TimeStampReq ::= SEQUENCE { 43 * version INTEGER { v1(1) }, 44 * messageImprint MessageImprint 45 * -- a hash algorithm OID and the hash value of the data to be 46 * -- time-stamped. 47 * reqPolicy TSAPolicyId OPTIONAL, 48 * nonce INTEGER OPTIONAL, 49 * certReq BOOLEAN DEFAULT FALSE, 50 * extensions [0] IMPLICIT Extensions OPTIONAL } 51 * 52 * MessageImprint ::= SEQUENCE { 53 * hashAlgorithm AlgorithmIdentifier, 54 * hashedMessage OCTET STRING } 55 * 56 * TSAPolicyId ::= OBJECT IDENTIFIER 57 * 58 * </pre> 59 * 60 * @since 1.5 61 * @author Vincent Ryan 62 * @see Timestamper 63 */ 64 65 public class TSRequest { 66 67 private static final ObjectIdentifier SHA1_OID; 68 private static final ObjectIdentifier MD5_OID; 69 static { 70 ObjectIdentifier sha1 = null; 71 ObjectIdentifier md5 = null; 72 try { 73 sha1 = new ObjectIdentifier("1.3.14.3.2.26"); 74 md5 = new ObjectIdentifier("1.2.840.113549.2.5"); 75 } catch (IOException ioe) { 76 // should not happen 77 } 78 SHA1_OID = sha1; 79 MD5_OID = md5; 80 } 81 82 private int version = 1; 83 84 private ObjectIdentifier hashAlgorithmId = null; 85 86 private byte[] hashValue; 87 88 private String policyId = null; 89 90 private BigInteger nonce = null; 91 92 private boolean returnCertificate = false; 93 94 private X509Extension[] extensions = null; 95 96 /** 97 * Constructs a timestamp request for the supplied hash value.. 98 * 99 * @param hashValue The hash value. This is the data to be timestamped. 100 * @param hashAlgorithm The name of the hash algorithm. 101 */ 102 public TSRequest(byte[] hashValue, String hashAlgorithm) { 103 104 // Check the common hash algorithms 105 if ("MD5".equalsIgnoreCase(hashAlgorithm)) { 106 hashAlgorithmId = MD5_OID; 107 // Check that the hash value matches the hash algorithm 108 assert hashValue.length == 16; 109 110 } else if ("SHA-1".equalsIgnoreCase(hashAlgorithm) || 111 "SHA".equalsIgnoreCase(hashAlgorithm) || 112 "SHA1".equalsIgnoreCase(hashAlgorithm)) { 113 hashAlgorithmId = SHA1_OID; 114 // Check that the hash value matches the hash algorithm 115 assert hashValue.length == 20; 116 117 } 118 // Clone the hash value 119 this.hashValue = new byte[hashValue.length]; 120 System.arraycopy(hashValue, 0, this.hashValue, 0, hashValue.length); 121 } 122 123 /** 124 * Sets the Time-Stamp Protocol version. 125 * 126 * @param version The TSP version. 127 */ 128 public void setVersion(int version) { 129 this.version = version; 130 } 131 132 /** 133 * Sets an object identifier for the Time-Stamp Protocol policy. 134 * 135 * @param version The policy object identifier. 136 */ 137 public void setPolicyId(String policyId) { 138 this.policyId = policyId; 139 } 140 141 /** 142 * Sets a nonce. 143 * A nonce is a single-use random number. 144 * 145 * @param nonce The nonce value. 146 */ 147 public void setNonce(BigInteger nonce) { 148 this.nonce = nonce; 149 } 150 151 /** 152 * Request that the TSA include its signing certificate in the response. 153 * 154 * @param returnCertificate True if the TSA should return its signing 155 * certificate. By default it is not returned. 156 */ 157 public void requestCertificate(boolean returnCertificate) { 158 this.returnCertificate = returnCertificate; 159 } 160 161 /** 162 * Sets the Time-Stamp Protocol extensions. 163 * 164 * @param extensions The protocol extensions. 165 */ 166 public void setExtensions(X509Extension[] extensions) { 167 this.extensions = extensions; 168 } 169 170 public byte[] encode() throws IOException { 171 172 DerOutputStream request = new DerOutputStream(); 173 174 // encode version 175 request.putInteger(version); 176 177 // encode messageImprint 178 DerOutputStream messageImprint = new DerOutputStream(); 179 DerOutputStream hashAlgorithm = new DerOutputStream(); 180 hashAlgorithm.putOID(hashAlgorithmId); 181 messageImprint.write(DerValue.tag_Sequence, hashAlgorithm); 182 messageImprint.putOctetString(hashValue); 183 request.write(DerValue.tag_Sequence, messageImprint); 184 185 // encode optional elements 186 187 if (policyId != null) { 188 request.putOID(new ObjectIdentifier(policyId)); 189 } 190 if (nonce != null) { 191 request.putInteger(nonce); 192 } 193 if (returnCertificate) { 194 request.putBoolean(true); 195 } 196 197 DerOutputStream out = new DerOutputStream(); 198 out.write(DerValue.tag_Sequence, request); 199 return out.toByteArray(); 200 } 201 }