/Frameworks/Core/ERExtensions/Sources/er/extensions/crypting/ERXAbstractBlowfishCrypter.java
Java | 222 lines | 128 code | 21 blank | 73 comment | 26 complexity | 0c217d4f619230fb13fc082dd91437a6 MD5 | raw file
- package er.extensions.crypting;
- import java.io.ByteArrayOutputStream;
- import java.security.Key;
- import javax.crypto.Cipher;
- import com.webobjects.foundation.NSForwardException;
- import er.extensions.foundation.ERXStringUtilities;
- /**
- * ERXAbstractBlowfishCrypter is a blowfish implementation of the crypter
- * interface that allows subclasses to override the source of the blowfish key.
- * The blowfish cipher is a two-way cipher meaning the original string that was
- * encrypted can be retrieved. The way that this version of the blowfish cipher
- * is encrypted it is safe to use as a form value.
- *
- * @author mschrag
- */
- public abstract class ERXAbstractBlowfishCrypter implements ERXCrypterInterface {
- /** Block size of blowfish encrypted strings */
- private int _blockSize;
- /** Used to cache the blowfish encryption cipher */
- private Cipher _encryptCipher;
- /** Used to cache the blowfish decryption cipher */
- private Cipher _decryptCipher;
- public ERXAbstractBlowfishCrypter() {
- _blockSize = 8;
- }
- /**
- * Sets the block size to use for this cipher.
- *
- * @param blockSize
- * the block size to use for this cipher
- */
- public void setBlockSize(int blockSize) {
- _blockSize = blockSize;
- }
- /**
- * Returns the block size for this cipher.
- *
- * @return the block size for this cipher
- */
- public int blockSize() {
- return _blockSize;
- }
- /**
- * Returns the secret key to use for this cipher.
- *
- * @return a secret key for the blowfish cipher
- */
- protected abstract Key secretBlowfishKey() throws Exception;
- /**
- * Creates a blowfish cipher for a given mode. The two possible modes for a
- * blowfish cipher are: ENCRYPT and DECRYPT.
- *
- * @param mode
- * of the cipher (encrypting or decrypting)
- * @return a blowfish cipher initialized with the given mode and with the
- * <code>secretKey</code> from the above method.
- */
- protected Cipher createBlowfishCipher(int mode) {
- try {
- Cipher cipher = Cipher.getInstance("Blowfish/ECB/NoPadding");
- cipher.init(mode, secretBlowfishKey());
- return cipher;
- }
- catch (java.security.NoSuchAlgorithmException ex) {
- throw new NSForwardException(ex, "Couldn't find the Blowfish algorithm; perhaps you do not have the SunJCE security provider installed properly?");
- }
- catch (Exception e) {
- throw new NSForwardException(e);
- }
- }
- /**
- * Method used to return the shared instance of the blowfish encryption
- * cipher.
- *
- * @return blowfish encryption cipher
- */
- protected Cipher encryptCipher() {
- if (_encryptCipher == null) {
- _encryptCipher = createBlowfishCipher(Cipher.ENCRYPT_MODE);
- }
- return _encryptCipher;
- }
- /**
- * Method used to return the shared instance of the blowfish decryption
- * cipher.
- *
- * @return blowfish decryption cipher
- */
- protected Cipher decryptCipher() {
- if (_decryptCipher == null) {
- _decryptCipher = createBlowfishCipher(Cipher.DECRYPT_MODE);
- }
- return _decryptCipher;
- }
- /**
- * Decodes a blowfish encoded string. Note that the originally encoded
- * string should have been encoded with the same secret key as is used for
- * the decoding cipher or else you are going to get garbage. To encode a
- * string have a look at <code>blowfishEncode</code>.
- *
- * @param cryptedText
- * blowfish encoded string to be decoded
- * @return decode clear text string
- */
- public String decrypt(String cryptedText) {
- if (cryptedText == null) {
- return null;
- }
- int length = cryptedText.length();
- if (length % 16 != 0) {
- return null;
- }
- ByteArrayOutputStream result = new ByteArrayOutputStream();
- byte[] clearText = null;
- byte[] encryptedBytes = new byte[_blockSize];
- int i = 0;
- for (int j = 0; j < length;) {
- char c1 = cryptedText.charAt(j++);
- int b1 = c1 < 'a' ? c1 - '0' : c1 - 'a' + 10;
- char c2 = cryptedText.charAt(j++);
- int b2 = c2 < 'a' ? c2 - '0' : c2 - 'a' + 10;
- encryptedBytes[i++] = (byte) ((b1 << 4) + b2);
- if (i == _blockSize) {
- // we filled a block
- try {
- clearText = decryptCipher().doFinal(encryptedBytes);
- }
- catch (Exception e) {
- throw new NSForwardException(e);
- }
- for (int k = 0; k < _blockSize; k++) {
- if (clearText[k] != 0) {
- result.write(clearText[k]);
- }
- }
- i = 0;
- }
- }
- if (i != 0) {
- for (int j = i; j < _blockSize; j++) {
- encryptedBytes[j] = 0;
- }
- try {
- clearText = decryptCipher().doFinal(encryptedBytes);
- }
- catch (Exception e) {
- throw new NSForwardException(e);
- }
- for (int k = 0; k < _blockSize; k++) {
- result.write(clearText[k]);
- }
- }
- return ERXStringUtilities.fromUTF8Bytes(result.toByteArray());
- }
- /**
- * Blowfish encodes a given string using the secret key specified in the
- * System property: <b>ERBlowfishCipherKey</b>. The blowfish cipher is a
- * two way cipher meaning that given the secret key you can de-cipher what
- * the original string is. For one-way encryption look at methods dealing
- * with the Sha alogrithm. To decode a blowfish encoded string use the
- * method: <code>blowfishDecode</code>. The resultant string from
- * encoding a string is safe for use in urls and cookies.
- *
- * @param clearText
- * string to be encrypted
- * @return encrypted string
- */
- public String encrypt(String clearText) {
- if (clearText == null) {
- return null;
- }
- byte clearTextBytes[] = ERXStringUtilities.toUTF8Bytes(clearText);
- StringBuilder result = new StringBuilder();
- int pos = 0, length = clearTextBytes.length;
- byte[] bytesToEncrypt = new byte[_blockSize];
- byte[] encryptedBytes = null;
- while (pos < length) {
- int k = 0;
- for (int j = pos; j < length && j < pos + _blockSize; k++, j++) {
- bytesToEncrypt[k] = clearTextBytes[j];
- }
- if (k < _blockSize) {
- for (int l = k; l < _blockSize; l++) {
- bytesToEncrypt[l] = 0;
- }
- }
- try {
- encryptedBytes = encryptCipher().doFinal(bytesToEncrypt);
- }
- catch (Exception e) {
- throw new NSForwardException(e);
- }
- for (k = 0; k < _blockSize; k++) {
- result.append(ERXStringUtilities.HEX_CHARS[(encryptedBytes[k] >>> 4) & 0xf]);
- result.append(ERXStringUtilities.HEX_CHARS[encryptedBytes[k] & 0xf]);
- }
- pos += _blockSize;
- }
- return result.toString();
- }
- }