Frames | No Frames |
1: /* RSAPKCS1V1_5Signature.java -- 2: Copyright (C) 2001, 2002, 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: import gnu.java.security.sig.BaseSignature; 45: 46: import java.math.BigInteger; 47: import java.security.PrivateKey; 48: import java.security.PublicKey; 49: import java.security.interfaces.RSAPrivateKey; 50: import java.security.interfaces.RSAPublicKey; 51: import java.util.Arrays; 52: 53: /** 54: * The RSA-PKCS1-V1.5 signature scheme is a digital signature scheme with 55: * appendix (SSA) combining the RSA algorithm with the EMSA-PKCS1-v1_5 encoding 56: * method. 57: * <p> 58: * References: 59: * <ol> 60: * <li><a 61: * href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip"> 62: * RSA-PSS Signature Scheme with Appendix, part B.</a><br> 63: * Primitive specification and supporting documentation.<br> 64: * Jakob Jonsson and Burt Kaliski.</li> 65: * <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography 66: * Standards (PKCS) #1:</a><br> 67: * RSA Cryptography Specifications Version 2.1.<br> 68: * Jakob Jonsson and Burt Kaliski.</li> 69: * </ol> 70: */ 71: public class RSAPKCS1V1_5Signature 72: extends BaseSignature 73: { 74: /** The underlying EMSA-PKCS1-v1.5 instance for this object. */ 75: private EMSA_PKCS1_V1_5 pkcs1; 76: 77: /** 78: * Default 0-arguments constructor. Uses SHA-1 as the default hash. 79: */ 80: public RSAPKCS1V1_5Signature() 81: { 82: this(Registry.SHA160_HASH); 83: } 84: 85: /** 86: * Constructs an instance of this object using the designated message digest 87: * algorithm as its underlying hash function. 88: * 89: * @param mdName the canonical name of the underlying hash function. 90: */ 91: public RSAPKCS1V1_5Signature(final String mdName) 92: { 93: this(HashFactory.getInstance(mdName)); 94: } 95: 96: public RSAPKCS1V1_5Signature(IMessageDigest md) 97: { 98: super(Registry.RSA_PKCS1_V1_5_SIG, md); 99: 100: pkcs1 = EMSA_PKCS1_V1_5.getInstance(md.name()); 101: } 102: 103: /** Private constructor for cloning purposes. */ 104: private RSAPKCS1V1_5Signature(final RSAPKCS1V1_5Signature that) 105: { 106: this(that.md.name()); 107: 108: this.publicKey = that.publicKey; 109: this.privateKey = that.privateKey; 110: this.md = (IMessageDigest) that.md.clone(); 111: this.pkcs1 = (EMSA_PKCS1_V1_5) that.pkcs1.clone(); 112: } 113: 114: public Object clone() 115: { 116: return new RSAPKCS1V1_5Signature(this); 117: } 118: 119: protected void setupForVerification(final PublicKey k) 120: throws IllegalArgumentException 121: { 122: if (! (k instanceof RSAPublicKey)) 123: throw new IllegalArgumentException(); 124: 125: publicKey = k; 126: } 127: 128: protected void setupForSigning(final PrivateKey k) 129: throws IllegalArgumentException 130: { 131: if (! (k instanceof RSAPrivateKey)) 132: throw new IllegalArgumentException(); 133: 134: privateKey = k; 135: } 136: 137: protected Object generateSignature() throws IllegalStateException 138: { 139: // 1. EMSA-PKCS1-v1_5 encoding: Apply the EMSA-PKCS1-v1_5 encoding 140: // operation (Section 9.2) to the message M to produce an encoded 141: // message EM of length k octets: 142: // 143: // EM = EMSA-PKCS1-V1_5-ENCODE (M, k). 144: // 145: // If the encoding operation outputs "message too long," output 146: // "message too long" and stop. If the encoding operation outputs 147: // "intended encoded message length too short," output "RSA modulus 148: // too short" and stop. 149: final int modBits = ((RSAPrivateKey) privateKey).getModulus().bitLength(); 150: final int k = (modBits + 7) / 8; 151: final byte[] EM = pkcs1.encode(md.digest(), k); 152: // 2. RSA signature: 153: // a. Convert the encoded message EM to an integer message epresentative 154: // m (see Section 4.2): m = OS2IP (EM). 155: final BigInteger m = new BigInteger(1, EM); 156: // b. Apply the RSASP1 signature primitive (Section 5.2.1) to the RSA 157: // private key K and the message representative m to produce an 158: // integer signature representative s: s = RSASP1 (K, m). 159: final BigInteger s = RSA.sign(privateKey, m); 160: // c. Convert the signature representative s to a signature S of length 161: // k octets (see Section 4.1): S = I2OSP (s, k). 162: // 3. Output the signature S. 163: return RSA.I2OSP(s, k); 164: } 165: 166: protected boolean verifySignature(final Object sig) 167: throws IllegalStateException 168: { 169: if (publicKey == null) 170: throw new IllegalStateException(); 171: final byte[] S = (byte[]) sig; 172: // 1. Length checking: If the length of the signature S is not k octets, 173: // output "invalid signature" and stop. 174: final int modBits = ((RSAPublicKey) publicKey).getModulus().bitLength(); 175: final int k = (modBits + 7) / 8; 176: if (S.length != k) 177: return false; 178: // 2. RSA verification: 179: // a. Convert the signature S to an integer signature representative 180: // s (see Section 4.2): s = OS2IP (S). 181: final BigInteger s = new BigInteger(1, S); 182: // b. Apply the RSAVP1 verification primitive (Section 5.2.2) to the 183: // RSA public key (n, e) and the signature representative s to 184: // produce an integer message representative m: 185: // m = RSAVP1 ((n, e), s). 186: // If RSAVP1 outputs "signature representative out of range," 187: // output "invalid signature" and stop. 188: final BigInteger m; 189: try 190: { 191: m = RSA.verify(publicKey, s); 192: } 193: catch (IllegalArgumentException x) 194: { 195: return false; 196: } 197: // c. Convert the message representative m to an encoded message EM 198: // of length k octets (see Section 4.1): EM = I2OSP (m, k). 199: // If I2OSP outputs "integer too large," output "invalid signature" 200: // and stop. 201: final byte[] EM; 202: try 203: { 204: EM = RSA.I2OSP(m, k); 205: } 206: catch (IllegalArgumentException x) 207: { 208: return false; 209: } 210: // 3. EMSA-PKCS1-v1_5 encoding: Apply the EMSA-PKCS1-v1_5 encoding 211: // operation (Section 9.2) to the message M to produce a second 212: // encoded message EM' of length k octets: 213: // EM' = EMSA-PKCS1-V1_5-ENCODE (M, k). 214: // If the encoding operation outputs "message too long," output 215: // "message too long" and stop. If the encoding operation outputs 216: // "intended encoded message length too short," output "RSA modulus 217: // too short" and stop. 218: final byte[] EMp = pkcs1.encode(md.digest(), k); 219: // 4. Compare the encoded message EM and the second encoded message EM'. 220: // If they are the same, output "valid signature"; otherwise, output 221: // "invalid signature." 222: return Arrays.equals(EM, EMp); 223: } 224: }