1 19 20 package com.maverick.crypto.publickey; 21 22 import java.io.IOException ; 23 24 import java.math.BigInteger ; 25 import com.maverick.crypto.security.SecureRandom; 26 27 public final class Rsa { 28 29 private static BigInteger ONE = BigInteger.valueOf(1); 30 31 public static BigInteger doPrivateCrt(BigInteger input, 32 BigInteger privateExponent, 33 BigInteger primeP, BigInteger primeQ, 34 BigInteger crtCoefficient) { 35 return doPrivateCrt(input, 36 primeP, primeQ, 37 getPrimeExponent(privateExponent, primeP), 38 getPrimeExponent(privateExponent, primeQ), 39 crtCoefficient); 40 } 41 42 public static BigInteger doPrivateCrt(BigInteger input, 43 BigInteger p, BigInteger q, 44 BigInteger dP, 45 BigInteger dQ, 46 BigInteger qInv) { 47 if (!qInv.equals(q.modInverse(p))) { 48 BigInteger t = p; 49 p = q; 50 q = t; 51 t = dP; 52 dP = dQ; 53 dQ = t; 54 } 55 56 BigInteger s_1 = input.modPow(dP, p); 57 BigInteger s_2 = input.modPow(dQ, q); 58 BigInteger h = qInv.multiply(s_1.subtract(s_2)).mod(p); 59 return s_2.add(h.multiply(q)); 60 61 } 62 63 public static BigInteger getPrimeExponent(BigInteger privateExponent, 64 BigInteger prime) { 65 BigInteger pe = prime.subtract(ONE); 66 return privateExponent.mod(pe); 67 } 68 69 public static BigInteger padPKCS1(BigInteger input, int type, 70 int padLen) throws 71 IllegalStateException { 72 BigInteger result; 73 BigInteger rndInt; 74 int inByteLen = (input.bitLength() + 7) / 8; 75 76 if (inByteLen > padLen - 11) { 77 throw new IllegalStateException ("PKCS1 failed to pad input! " 78 + "input=" + String.valueOf(inByteLen) 79 + " padding=" + String.valueOf(padLen)); 80 } 81 82 byte[] padBytes = new byte[ (padLen - inByteLen - 3) + 1]; 83 padBytes[0] = 0; 84 85 for (int i = 1; i < (padLen - inByteLen - 3 + 1); i++) { 86 if (type == 0x01) { 87 padBytes[i] = (byte) 0xff; 88 } 89 else { 90 byte[] b = new byte[1]; 91 do { 92 SecureRandom.getInstance().nextBytes(b); 93 } 94 while (b[0] == 0); 95 padBytes[i] = b[0]; 96 } 97 } 98 99 rndInt = new BigInteger (1, padBytes); 100 rndInt = rndInt.shiftLeft( (inByteLen + 1) * 8); 101 result = BigInteger.valueOf(type); 102 result = result.shiftLeft( (padLen - 2) * 8); 103 result = result.or(rndInt); 104 result = result.or(input); 105 106 return result; 107 } 108 109 public static BigInteger removePKCS1(BigInteger input, int type) throws 110 IllegalStateException { 111 byte[] strip = input.toByteArray(); 112 byte[] val; 113 int i; 114 115 if (strip[0] != type) { 116 throw new IllegalStateException ("PKCS1 padding type " + 117 type + " is not valid"); 118 } 119 120 for (i = 1; i < strip.length; i++) { 121 if (strip[i] == 0) { 122 break; 123 } 124 if (type == 0x01 && strip[i] != (byte) 0xff) { 125 throw new IllegalStateException ("Corrupt data found in expected PKSC1 padding"); 126 } 127 } 128 129 if (i == strip.length) { 130 throw new IllegalStateException ("Corrupt data found in expected PKSC1 padding"); 131 } 132 133 val = new byte[strip.length - i]; 134 System.arraycopy(strip, i, val, 0, val.length); 135 return new BigInteger (1, val); 136 } 137 138 public static RsaPrivateCrtKey generateKey(int bits, SecureRandom secRand) { 139 return generateKey(bits, BigInteger.valueOf(0x10001L), secRand); 140 } 141 142 public static RsaPrivateCrtKey generateKey(int bits, BigInteger e, 143 SecureRandom secRand) { 144 BigInteger p = null; 145 BigInteger q = null; 146 BigInteger t = null; 147 BigInteger phi = null; 148 BigInteger d = null; 149 BigInteger u = null; 150 BigInteger n = null; 151 boolean finished = false; 152 BigInteger ONE = BigInteger.valueOf(1); 153 154 int pbits = (bits + 1) / 2; 155 int qbits = bits - pbits; 156 157 while (!finished) { 158 p = new BigInteger (pbits, 80, secRand); 159 q = new BigInteger (qbits, 80, secRand); 160 161 if (p.compareTo(q) == 0) { 162 continue; 163 } 164 else if (p.compareTo(q) < 0) { 165 t = q; 166 q = p; 167 p = t; 168 } 169 170 if (!p.isProbablePrime(25)) 171 continue; 172 173 if(!q.isProbablePrime(25)) 174 continue; 175 176 t = p.gcd(q); 177 if (t.compareTo(ONE) != 0) { 178 continue; 179 } 180 181 n = p.multiply(q); 182 183 if (n.bitLength() != bits) { 184 continue; 185 } 186 187 phi = p.subtract(ONE).multiply(q.subtract(ONE)); 188 d = e.modInverse(phi); 189 u = q.modInverse(p); 190 191 finished = true; 192 } 193 194 return new RsaPrivateCrtKey(n, e, d, p, q, 195 Rsa.getPrimeExponent(d, p), 196 Rsa.getPrimeExponent(d, q), 197 u); 198 199 200 } 201 202 public static BigInteger doPublic(BigInteger input, BigInteger modulus, 203 BigInteger publicExponent) { 204 return input.modPow(publicExponent, modulus); 205 } 206 207 public static BigInteger doPrivate(BigInteger input, BigInteger modulus, 208 BigInteger privateExponent) { 209 return doPublic(input, modulus, privateExponent); 210 } 211 212 } 213 | Popular Tags |