/** * Encrypts the given message using reverse RSA (encrypts with the private key) and returns the * ciphertext of the message in String form or null if the message could not be encrypted * * @param msg != null * @return ciphertext form of the message made from RSA encryption or null if the message could * not be encrypted */ public String encryptRSA(String msg) { try { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, privRSAKey); byte[] msgBytes = msg.getBytes(); String result = ""; for (int i = 0; i < (int) Math.ceil(msgBytes.length * 1.0 / 100); i++) { byte[] c = cipher.doFinal( Arrays.copyOfRange(msgBytes, i * 100, Math.min((i + 1) * 100, msgBytes.length))); result += new Base64().encodeToString(c); } return result.replace("\r\n", "_").replace("\r", "~").replace("\n", "::"); } catch (Exception e) { System.out.println("Could not encrypt the message with RSA"); if (DEBUG) { e.printStackTrace(); } return null; } }
/** * Decrypts the given encrypted message using reverse RSA, meaning that it uses the public key to * decrypt, and returns the decrypte message or null if the message could not be decrypted * * @param encMsg != null and encrypted with either this object or a similar object that has the * proper decryption parameters * @return the string representation of the message that was decrypted or null if the message * could not be decrypted */ public String decryptRSA(String encMsg) { try { encMsg = encMsg.replace("::", "\n").replace("~", "\r").replace("_", "\r\n"); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, pubRSAKey); String result = ""; for (int i = 0; i < encMsg.length() / 178; i++) { String subMsg = encMsg.substring(i * 178, Math.min((i + 1) * 178, encMsg.length())); byte[] msgBytes = cipher.doFinal(new Base64().decode(subMsg)); result += new String(msgBytes); } return result; } catch (Exception e) { System.out.println("Could not decrypt the message with RSA"); if (DEBUG) { e.printStackTrace(); } return null; } }
// Uses supplied hash algorithm static byte[] derive( char[] chars, byte[] salt, int ic, int n, int type, String hashAlgo, int blockLength) { // Add in trailing NULL terminator. Special case: // no terminator if password is "\0". int length = chars.length * 2; if (length == 2 && chars[0] == 0) { chars = new char[0]; length = 0; } else { length += 2; } byte[] passwd = new byte[length]; for (int i = 0, j = 0; i < chars.length; i++, j += 2) { passwd[j] = (byte) ((chars[i] >>> 8) & 0xFF); passwd[j + 1] = (byte) (chars[i] & 0xFF); } byte[] key = new byte[n]; try { MessageDigest sha = MessageDigest.getInstance(hashAlgo); int v = blockLength; int u = sha.getDigestLength(); int c = roundup(n, u) / u; byte[] D = new byte[v]; int s = roundup(salt.length, v); int p = roundup(passwd.length, v); byte[] I = new byte[s + p]; Arrays.fill(D, (byte) type); concat(salt, I, 0, s); concat(passwd, I, s, p); byte[] Ai; byte[] B = new byte[v]; byte[] tmp = new byte[v]; int i = 0; for (; ; i++, n -= u) { sha.update(D); sha.update(I); Ai = sha.digest(); for (int r = 1; r < ic; r++) Ai = sha.digest(Ai); System.arraycopy(Ai, 0, key, u * i, Math.min(n, u)); if (i + 1 == c) break; concat(Ai, B, 0, B.length); BigInteger B1; B1 = new BigInteger(1, B).add(BigInteger.ONE); for (int j = 0; j < I.length; j += v) { BigInteger Ij; int trunc; if (tmp.length != v) tmp = new byte[v]; System.arraycopy(I, j, tmp, 0, v); Ij = new BigInteger(1, tmp); Ij = Ij.add(B1); tmp = Ij.toByteArray(); trunc = tmp.length - v; if (trunc >= 0) { System.arraycopy(tmp, trunc, I, j, v); } else if (trunc < 0) { Arrays.fill(I, j, j + (-trunc), (byte) 0); System.arraycopy(tmp, 0, I, j + (-trunc), tmp.length); } } } } catch (Exception e) { throw new RuntimeException("internal error: " + e); } return key; }