Frames | No Frames |
1: /* EMSA_PKCS1_V1_5.java -- 2: Copyright (C) 2003, 2006 Free Software Foundation, Inc. 3: 4: This file is a part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2 of the License, or (at 9: your option) any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; if not, write to the Free Software 18: Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 19: USA 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package gnu.java.security.sig.rsa; 40: 41: import gnu.java.security.Registry; 42: import gnu.java.security.hash.HashFactory; 43: import gnu.java.security.hash.IMessageDigest; 44: 45: import java.io.ByteArrayOutputStream; 46: 47: /** 48: * An implementation of the EMSA-PKCS1-V1.5 encoding scheme. 49: * <p> 50: * EMSA-PKCS1-V1.5 is parameterised by the choice of hash function Hash and 51: * hLen which denotes the length in octets of the hash function output. 52: * <p> 53: * References: 54: * <ol> 55: * <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography 56: * Standards (PKCS) #1:</a><br> 57: * RSA Cryptography Specifications Version 2.1.<br> 58: * Jakob Jonsson and Burt Kaliski.</li> 59: * </ol> 60: */ 61: public class EMSA_PKCS1_V1_5 62: implements Cloneable 63: { 64: /* Notes. 65: 1. For the six hash functions mentioned in Appendix B.1, the DER encoding 66: T of the DigestInfo value is equal to the following: 67: 68: MD2: (0x)30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 02 05 00 04 10 || H 69: MD5: (0x)30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 05 05 00 04 10 || H 70: SHA-1: (0x)30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14 || H 71: SHA-256: (0x)30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || H 72: SHA-384: (0x)30 41 30 0d 06 09 60 86 48 01 65 03 04 02 02 05 00 04 30 || H 73: SHA-512: (0x)30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40 || H 74: */ 75: private static final byte[] MD2_PREFIX = { 76: (byte) 0x30, (byte) 0x20, (byte) 0x30, (byte) 0x0c, (byte) 0x06, 77: (byte) 0x08, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, 78: (byte) 0xf7, (byte) 0x0d, (byte) 0x02, (byte) 0x02, (byte) 0x05, 79: (byte) 0x00, (byte) 0x04, (byte) 0x10 80: }; 81: 82: private static final byte[] MD5_PREFIX = { 83: (byte) 0x30, (byte) 0x20, (byte) 0x30, (byte) 0x0c, (byte) 0x06, 84: (byte) 0x08, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, 85: (byte) 0xf7, (byte) 0x0d, (byte) 0x02, (byte) 0x05, (byte) 0x05, 86: (byte) 0x00, (byte) 0x04, (byte) 0x10 87: }; 88: 89: private static final byte[] SHA160_PREFIX = { 90: (byte) 0x30, (byte) 0x21, (byte) 0x30, (byte) 0x09, (byte) 0x06, 91: (byte) 0x05, (byte) 0x2b, (byte) 0x0e, (byte) 0x03, (byte) 0x02, 92: (byte) 0x1a, (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x14 93: }; 94: 95: private static final byte[] SHA256_PREFIX = { 96: (byte) 0x30, (byte) 0x31, (byte) 0x30, (byte) 0x0d, (byte) 0x06, 97: (byte) 0x09, (byte) 0x60, (byte) 0x86, (byte) 0x48, (byte) 0x01, 98: (byte) 0x65, (byte) 0x03, (byte) 0x04, (byte) 0x02, (byte) 0x01, 99: (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x20 100: }; 101: 102: private static final byte[] SHA384_PREFIX = { 103: (byte) 0x30, (byte) 0x41, (byte) 0x30, (byte) 0x0d, (byte) 0x06, 104: (byte) 0x09, (byte) 0x60, (byte) 0x86, (byte) 0x48, (byte) 0x01, 105: (byte) 0x65, (byte) 0x03, (byte) 0x04, (byte) 0x02, (byte) 0x02, 106: (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x30 107: }; 108: 109: private static final byte[] SHA512_PREFIX = { 110: (byte) 0x30, (byte) 0x51, (byte) 0x30, (byte) 0x0d, (byte) 0x06, 111: (byte) 0x09, (byte) 0x60, (byte) 0x86, (byte) 0x48, (byte) 0x01, 112: (byte) 0x65, (byte) 0x03, (byte) 0x04, (byte) 0x02, (byte) 0x03, 113: (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x40 114: }; 115: 116: /** The underlying hash function to use with this instance. */ 117: private IMessageDigest hash; 118: 119: /** The output size of the hash function in octets. */ 120: private int hLen; // TODO: field not used!!! investigate 121: 122: /** The DER part of DigestInfo not containing the hash value itself. */ 123: private byte[] prefix; 124: 125: /** 126: * Trivial private constructor to enforce use through Factory method. 127: * 128: * @param hash the message digest instance to use with this scheme instance. 129: */ 130: private EMSA_PKCS1_V1_5(final IMessageDigest hash) 131: { 132: super(); 133: 134: this.hash = hash; 135: hLen = hash.hashSize(); 136: final String name = hash.name(); 137: if (name.equals(Registry.MD2_HASH)) 138: prefix = MD2_PREFIX; 139: else if (name.equals(Registry.MD5_HASH)) 140: prefix = MD5_PREFIX; 141: else if (name.equals(Registry.SHA160_HASH)) 142: prefix = SHA160_PREFIX; 143: else if (name.equals(Registry.SHA256_HASH)) 144: prefix = SHA256_PREFIX; 145: else if (name.equals(Registry.SHA384_HASH)) 146: prefix = SHA384_PREFIX; 147: else if (name.equals(Registry.SHA512_HASH)) 148: prefix = SHA512_PREFIX; 149: else 150: throw new UnsupportedOperationException(); // should not happen 151: } 152: 153: /** 154: * Returns an instance of this object given a designated name of a hash 155: * function. 156: * 157: * @param mdName the canonical name of a hash function. 158: * @return an instance of this object configured for use with the designated 159: * options. 160: * @throws UnsupportedOperationException if the hash function is not 161: * implemented or does not have an ID listed in RFC-3447. 162: */ 163: public static final EMSA_PKCS1_V1_5 getInstance(final String mdName) 164: { 165: final IMessageDigest hash = HashFactory.getInstance(mdName); 166: final String name = hash.name(); 167: if (! (name.equals(Registry.MD2_HASH) 168: || name.equals(Registry.MD5_HASH) 169: || name.equals(Registry.SHA160_HASH) 170: || name.equals(Registry.SHA256_HASH) 171: || name.equals(Registry.SHA384_HASH) 172: || name.equals(Registry.SHA512_HASH))) 173: throw new UnsupportedOperationException("hash with no OID: " + name); 174: 175: return new EMSA_PKCS1_V1_5(hash); 176: } 177: 178: public Object clone() 179: { 180: return getInstance(hash.name()); 181: } 182: 183: /** 184: * Frames the hash of a message, along with an ID of the hash function in 185: * a DER sequence according to the specifications of EMSA-PKCS1-V1.5 as 186: * described in RFC-3447 (see class documentation). 187: * 188: * @param mHash the byte sequence resulting from applying the message digest 189: * algorithm Hash to the message <i>M</i>. 190: * @param emLen intended length in octets of the encoded message, at least 191: * <code>tLen + 11</code>, where <code>tLen</code> is the octet length of the 192: * DER encoding <code>T</code> of a certain value computed during the 193: * encoding operation. 194: * @return encoded message, an octet string of length <code>emLen</code>. 195: * @throws IllegalArgumentException if the message is too long, or if the 196: * intended encoded message length is too short. 197: */ 198: public byte[] encode(final byte[] mHash, final int emLen) 199: { 200: // 1. Apply the hash function to the message M to produce a hash value 201: // H: H = Hash(M). 202: // If the hash function outputs "message too long," output "message 203: // too long" and stop. 204: // 2. Encode the algorithm ID for the hash function and the hash value 205: // into an ASN.1 value of type DigestInfo (see Appendix A.2.4) with 206: // the Distinguished Encoding Rules (DER), where the type DigestInfo 207: // has the syntax 208: // DigestInfo ::= SEQUENCE { 209: // digestAlgorithm AlgorithmIdentifier, 210: // digest OCTET STRING 211: // } 212: // The first field identifies the hash function and the second contains 213: // the hash value. Let T be the DER encoding of the DigestInfo value 214: // (see the notes below) and let tLen be the length in octets of T. 215: final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 216: baos.write(prefix, 0, prefix.length); 217: baos.write(mHash, 0, mHash.length); 218: final byte[] T = baos.toByteArray(); 219: final int tLen = T.length; 220: // 3. If emLen < tLen + 11, output "intended encoded message length too 221: // short" and stop. 222: if (emLen < tLen + 11) 223: throw new IllegalArgumentException("emLen too short"); 224: // 4. Generate an octet string PS consisting of emLen - tLen - 3 octets 225: // with hexadecimal value 0xff. The length of PS will be at least 8 226: // octets. 227: final byte[] PS = new byte[emLen - tLen - 3]; 228: for (int i = 0; i < PS.length; i++) 229: PS[i] = (byte) 0xFF; 230: // 5. Concatenate PS, the DER encoding T, and other padding to form the 231: // encoded message EM as: EM = 0x00 || 0x01 || PS || 0x00 || T. 232: baos.reset(); 233: baos.write(0x00); 234: baos.write(0x01); 235: baos.write(PS, 0, PS.length); 236: baos.write(0x00); 237: baos.write(T, 0, tLen); 238: final byte[] result = baos.toByteArray(); 239: baos.reset(); 240: // 6. Output EM. 241: return result; 242: } 243: }