Share Pastebin
Guest
Public paste!

blaufish

By: a guest | Oct 14th, 2009 | Syntax: Java | Size: 6.42 KB | Hits: 203 | Expires: Never
Copy text to clipboard
  1. /*
  2.  * Blaufish's HMAC'ed and IV:ed encryptor/decryptor
  3.  * http://blaufish.blogg.se/
  4.  *
  5.  * Some rights reserved;
  6.  * http://creativecommons.org/licenses/by-nc-sa/3.0/
  7.  *
  8.  */
  9. import java.security.InvalidAlgorithmParameterException;
  10. import java.security.InvalidKeyException;
  11. import java.security.NoSuchAlgorithmException;
  12. import java.security.SecureRandom;
  13. import java.security.spec.AlgorithmParameterSpec;
  14. import java.security.spec.InvalidKeySpecException;
  15. import java.util.Arrays;
  16.  
  17. import javax.crypto.BadPaddingException;
  18. import javax.crypto.Cipher;
  19. import javax.crypto.IllegalBlockSizeException;
  20. import javax.crypto.Mac;
  21. import javax.crypto.NoSuchPaddingException;
  22. import javax.crypto.SecretKey;
  23. import javax.crypto.SecretKeyFactory;
  24. import javax.crypto.spec.IvParameterSpec;
  25. import javax.crypto.spec.SecretKeySpec;
  26.  
  27. import org.apache.commons.codec.binary.Base64;
  28. import org.junit.Test;
  29.  
  30. public class TestIsATest {
  31.         private static final String HMAC_ALGORTIHM = "HmacSHA1";
  32.  
  33.         @Test
  34.         public void test1() throws Exception {
  35.                 SecureRandom rnd = new SecureRandom();
  36.  
  37.                 byte[] keybytes24 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
  38.                                 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 };
  39.  
  40.                 byte[] iv = new byte[8];
  41.                 rnd.nextBytes(iv);
  42.  
  43.                 testEncryption(keybytes24, iv, "DESEDE", "/CBC/PKCS5Padding");
  44.         }
  45.  
  46.         @Test
  47.         public void test2() throws Exception {
  48.                 SecureRandom rnd = new SecureRandom();
  49.  
  50.                 byte[] keybytes24 = new byte[24];
  51.                 rnd.nextBytes(keybytes24);
  52.  
  53.                 byte[] iv = new byte[8];
  54.                 rnd.nextBytes(iv);
  55.  
  56.                 testEncryption(keybytes24, iv, "DESEDE", "/CBC/PKCS5Padding");
  57.         }
  58.  
  59.         @Test
  60.         public void test3() throws Exception {
  61.                 SecureRandom rnd = new SecureRandom();
  62.  
  63.                 byte[] keybytes8 = new byte[8];
  64.                 rnd.nextBytes(keybytes8);
  65.  
  66.                 byte[] iv = new byte[8];
  67.                 rnd.nextBytes(iv);
  68.  
  69.                 testEncryption(keybytes8, iv, "DES", "/CBC/PKCS5Padding");
  70.         }
  71.  
  72.         @Test
  73.         public void test4() throws Exception {
  74.                 SecureRandom rnd = new SecureRandom();
  75.  
  76.                 byte[] keybytes16 = new byte[16];
  77.                 rnd.nextBytes(keybytes16);
  78.  
  79.                 byte[] iv = new byte[16];
  80.                 rnd.nextBytes(iv);
  81.  
  82.                 testEncryption(keybytes16, iv, "AES", "/CBC/PKCS5Padding");
  83.         }
  84.  
  85.         @Test
  86.         public void test5() throws Exception {
  87.                 SecureRandom rnd = new SecureRandom();
  88.  
  89.                 byte[] keybytes16 = new byte[16];
  90.                 rnd.nextBytes(keybytes16);
  91.  
  92.                 byte[] iv = new byte[8];
  93.                 rnd.nextBytes(iv);
  94.  
  95.                 testEncryption(keybytes16, iv, "blowfish", "/CBC/PKCS5Padding");
  96.         }
  97.  
  98.         static void testEncryption(byte[] keybytes, byte[] iv,
  99.                         final String algorithm, String algorithmModifiers)
  100.                         throws NoSuchAlgorithmException, NoSuchPaddingException,
  101.                         InvalidKeyException, IllegalBlockSizeException,
  102.                         BadPaddingException, InvalidKeySpecException,
  103.                         InvalidAlgorithmParameterException {
  104.  
  105.                 byte[] cleartext = "This is just an example".getBytes();
  106.                 String encrypted = encrypt(keybytes, iv, cleartext, algorithm,
  107.                                 algorithmModifiers);
  108.  
  109.                 byte[] cleartext1 = decrypt(keybytes, encrypted, algorithm,
  110.                                 algorithmModifiers);
  111.  
  112.                 System.out.println(new String(cleartext1));
  113.  
  114.         }
  115.  
  116.         private static String encrypt(byte[] keybytes, byte[] iv, byte[] cleartext,
  117.                         final String algorithm, String algorithmModifiers)
  118.                         throws NoSuchAlgorithmException, InvalidKeyException,
  119.                         NoSuchPaddingException, InvalidAlgorithmParameterException,
  120.                         IllegalBlockSizeException, BadPaddingException {
  121.                 SecretKey key = generateKey(keybytes, algorithm);
  122.  
  123.                 Mac mac = Mac.getInstance(HMAC_ALGORTIHM);
  124.                 Cipher cipher;
  125.                 cipher = Cipher.getInstance(algorithm + algorithmModifiers);
  126.  
  127.                 AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
  128.                 cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
  129.  
  130.                 byte[] ciphertext = cipher.doFinal(cleartext);
  131.  
  132.                 mac.init(key);
  133.                 byte[] keyedDigest = mac.doFinal(cleartext);
  134.  
  135.                 TupleIvCiphertextMac icm = new TupleIvCiphertextMac(iv, ciphertext,
  136.                                 keyedDigest);
  137.                 return icm.generateEncodedString();
  138.         }
  139.  
  140.         private static byte[] decrypt(byte[] keybytes, String encryptedString,
  141.                         final String algorithm, String algorithmModifiers)
  142.                         throws NoSuchAlgorithmException, InvalidKeyException,
  143.                         NoSuchPaddingException, InvalidAlgorithmParameterException,
  144.                         IllegalBlockSizeException, BadPaddingException {
  145.  
  146.                 TupleIvCiphertextMac icm = new TupleIvCiphertextMac(encryptedString);
  147.  
  148.                 SecretKey key = generateKey(keybytes, algorithm);
  149.  
  150.                 Mac mac = Mac.getInstance(HMAC_ALGORTIHM);
  151.                 Cipher cipher;
  152.                 cipher = Cipher.getInstance(algorithm + algorithmModifiers);
  153.  
  154.                 AlgorithmParameterSpec paramSpec = new IvParameterSpec(icm.iv);
  155.                 cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
  156.  
  157.                 byte[] cleartext = cipher.doFinal(icm.ciphertext);
  158.  
  159.                 mac.init(key);
  160.                 byte[] keyedDigest = mac.doFinal(cleartext);
  161.  
  162.                 if (!Arrays.equals(keyedDigest, icm.mac)) {
  163.                         throw new RuntimeException("MAC failure");
  164.                 }
  165.  
  166.                 return cleartext;
  167.         }
  168.  
  169.         private static SecretKey generateKey(byte[] keybytes, String algorithm)
  170.                         throws NoSuchAlgorithmException, InvalidKeyException {
  171.                 SecretKey secretKey = new SecretKeySpec(keybytes, algorithm);
  172.  
  173.                 if (algorithm.contains("DES")) {
  174.                         SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
  175.                         secretKey = skf.translateKey(secretKey);
  176.                 }
  177.                 return secretKey;
  178.         }
  179.  
  180.         private static class TupleIvCiphertextMac {
  181.                 private static final char FIELD_SEPARATOR = ':';
  182.                 byte[] iv;
  183.                 byte[] ciphertext;
  184.                 byte[] mac;
  185.  
  186.                 TupleIvCiphertextMac(byte[] iv, byte[] ciphertext, byte[] mac) {
  187.                         this.iv = iv;
  188.                         this.ciphertext = ciphertext;
  189.                         this.mac = mac;
  190.                 }
  191.  
  192.                 String generateEncodedString() {
  193.                         String sIV = Base64.encodeBase64String(iv);
  194.                         String sCiphertext = Base64.encodeBase64String(ciphertext);
  195.                         String sMac = Base64.encodeBase64String(mac);
  196.  
  197.                         StringBuilder sb = new StringBuilder().append(sIV).append(
  198.                                         FIELD_SEPARATOR).append(sCiphertext)
  199.                                         .append(FIELD_SEPARATOR).append(sMac);
  200.                         return sb.toString();
  201.                 }
  202.  
  203.                 TupleIvCiphertextMac(String encodedString) {
  204.                         int separator1 = encodedString.indexOf(FIELD_SEPARATOR);
  205.                         int separator2 = encodedString.lastIndexOf(FIELD_SEPARATOR);
  206.                         if (separator1 == separator2) {
  207.                                 throw new IllegalArgumentException();
  208.                         }
  209.                         String sIV = encodedString.substring(0, separator1 - 1);
  210.                         String sCiphertext = encodedString.substring(separator1 + 1,
  211.                                         separator2 - 1);
  212.                         String sMac = encodedString.substring(separator2 + 1);
  213.  
  214.                         iv = Base64.decodeBase64(sIV);
  215.                         ciphertext = Base64.decodeBase64(sCiphertext);
  216.                         mac = Base64.decodeBase64(sMac);
  217.                 }
  218.         }
  219. }