Java crypto library:

Example:
  1. Crypto _c = new Crypto();  
  2. Crypto.AES aes = _c .new AES();  
  3.   
  4. int keySizeInBits = 128;                                       
  5. int keySizeInBytes = keySizeInBits/8;    
  6.   
  7. // Derive a cryptographic key: PBKDF2  
  8. String salt = Utils.byteArrayToHexString(Utils.getRandomBytes(8));  
  9. String key = Utils.pbkdf2("Secret Passphrase", salt, 1000, keySizeInBytes);  
  10.   
  11. // generate IV  
  12. byte[] ivBytes = aes.generateIV();  
  13. aes.setIV(ivBytes);  
  14.   
  15. /*** encrypt */    
  16. String ciphertext = aes.encrypt("plaintext", key);  
  17.   
  18. /*** decrypt */    
  19. String plaintext = aes.decrypt(ciphertext, key);   

Example JCrypto: JCrypto.jar

image


Library:
  1. package it.polito.ai;  
  2.   
  3. import java.security.InvalidKeyException;  
  4. import java.security.Key;  
  5. import java.security.KeyFactory;  
  6. import java.security.KeyPair;  
  7. import java.security.KeyPairGenerator;  
  8. import java.security.MessageDigest;  
  9. import java.security.NoSuchAlgorithmException;  
  10. import java.security.SecureRandom;  
  11. import java.security.InvalidAlgorithmParameterException;  
  12. import java.security.NoSuchProviderException;  
  13. import java.security.spec.InvalidKeySpecException;  
  14. import java.security.spec.InvalidParameterSpecException;  
  15. import java.security.spec.RSAPublicKeySpec;  
  16.   
  17. import java.util.regex.Pattern;  
  18. import java.util.Random;  
  19.   
  20. import java.io.UnsupportedEncodingException;  
  21. import java.math.BigInteger;  
  22. import java.nio.charset.Charset;  
  23.   
  24. import javax.crypto.BadPaddingException;  
  25. import javax.crypto.Cipher;  
  26. import javax.crypto.IllegalBlockSizeException;  
  27. import javax.crypto.KeyGenerator;  
  28. import javax.crypto.Mac;  
  29. import javax.crypto.NoSuchPaddingException;  
  30. import javax.crypto.SecretKey;  
  31. import javax.crypto.spec.IvParameterSpec;  
  32. import javax.crypto.spec.SecretKeySpec;  
  33.   
  34. public class Crypto   
  35. {  
  36.   
  37.     /* 
  38.      * AES 
  39.      */  
  40.     public class AES   
  41.     {  
  42.            private final String ALGORITHM = "AES";                               // symmetric algorithm for data encryption  
  43.            private final String MODE = "CBC";      
  44.            private final String PADDING = "PKCS5Padding";                        // Padding for symmetric algorithm  
  45.            private final String CIPHER_TRANSFORMATION = ALGORITHM + "/" + MODE + "/" + PADDING;       
  46.            private Charset PLAIN_TEXT_ENCODING = Charset.forName("UTF-8");       // character encoding  
  47.            //private final String CRYPTO_PROVIDER = "SunMSCAPI";                 // provider for the crypto  
  48.            private int KEY_SIZE_BITS = 128;                                      /* symmetric key size (128, 192, 256)  
  49.                                                                                   * if using 256 you must have the Java Cryptography Extension (JCE)  
  50.                                                                                   * Unlimited Strength Jurisdiction Policy Files installed */  
  51.            private int KEY_SIZE_BYTES = KEY_SIZE_BITS/8;          
  52.              
  53.            private Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);  
  54.            private byte[] ivBytes = new byte[KEY_SIZE_BYTES];  
  55.            private SecretKey key;  
  56.   
  57.            public AES()   
  58.                    throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException,   
  59.                    InvalidParameterSpecException, InvalidKeyException, InvalidAlgorithmParameterException  
  60.            {  
  61.                KeyGenerator kgen = KeyGenerator.getInstance(ALGORITHM);  
  62.                kgen.init(KEY_SIZE_BITS);   
  63.                key = kgen.generateKey();  
  64.                cipher.init(Cipher.ENCRYPT_MODE, key);  
  65.                ivBytes = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();  
  66.            }  
  67.              
  68.            public String getIVAsHex()  
  69.            {  
  70.                return Utils.byteArrayToHexString(ivBytes);  
  71.            }  
  72.   
  73.            public String getKeyAsHex()  
  74.            {  
  75.                return Utils.byteArrayToHexString(key.getEncoded());  
  76.            }  
  77.   
  78.            public void setStringToKey(String keyText) throws NoSuchAlgorithmException, UnsupportedEncodingException  
  79.            {  
  80.                setKey(keyText.getBytes());  
  81.            }  
  82.   
  83.            public void setHexToKey(String hexKey)  
  84.            {  
  85.                setKey(Utils.hexStringToByteArray(hexKey));  
  86.            }  
  87.   
  88.            public void setKey(byte[] bArray)  
  89.            {  
  90.                byte[] bText = new byte[KEY_SIZE_BYTES];  
  91.                int end = Math.min(KEY_SIZE_BYTES, bArray.length);  
  92.                System.arraycopy(bArray, 0, bText, 0, end);  
  93.                key = new SecretKeySpec(bText, ALGORITHM);  
  94.            }  
  95.   
  96.            public void setStringToIV(String ivText)  
  97.            {  
  98.                setIV(ivText.getBytes());  
  99.            }  
  100.   
  101.            public void setHexToIV(String hexIV)  
  102.            {  
  103.                setIV(Utils.hexStringToByteArray(hexIV));  
  104.            }  
  105.   
  106.            public void setIV(byte[] bArray)  
  107.            {  
  108.                byte[] bText = new byte[KEY_SIZE_BYTES];  
  109.                int end = Math.min(KEY_SIZE_BYTES, bArray.length);  
  110.                System.arraycopy(bArray, 0, bText, 0, end);  
  111.                ivBytes = bText;  
  112.            }  
  113.              
  114.            public byte[] generateIV()  
  115.            {  
  116.                 byte[] iv = Utils.getRandomBytes(KEY_SIZE_BYTES);  
  117.                 return iv;  
  118.            }  
  119.   
  120.            public String encrypt(String plaintext, String passphrase)   
  121.                     throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException,   
  122.                     InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException  
  123.            {  
  124.                 if (plaintext.length() == 0return null;  
  125.                   
  126.                 setStringToKey(passphrase);  
  127.   
  128.                 cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(ivBytes));  
  129.                 byte[] encrypted = cipher.doFinal(plaintext.getBytes(PLAIN_TEXT_ENCODING));  
  130.                 return Utils.byteArrayToBase64String(encrypted);  
  131.            }  
  132.   
  133.            public String decrypt(String ciphertext, String passphrase)   
  134.                     throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException,   
  135.                     InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException   
  136.            {  
  137.                 if (ciphertext.length() == 0return null;  
  138.                   
  139.                 setStringToKey(passphrase);  
  140.   
  141.                 byte[] dec = Utils.base64StringToByteArray(ciphertext);  
  142.                 cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(ivBytes));  
  143.                 byte[] decrypted = cipher.doFinal(dec);  
  144.                 return new String(decrypted, PLAIN_TEXT_ENCODING);  
  145.            }  
  146.     }  
  147.       
  148.     /* 
  149.      * PBKDF2: deriveKey 
  150.      */  
  151.     private static class PBKDF2  
  152.     {  
  153.         private static byte[] deriveKey(byte[] password, byte[] salt, int iterationCount, int dkLen)  
  154.             throws NoSuchAlgorithmException, InvalidKeyException  
  155.         {  
  156.             SecretKeySpec keyspec = new SecretKeySpec(password, "HmacSHA256");  
  157.             Mac prf = Mac.getInstance("HmacSHA256");  
  158.             prf.init( keyspec );  
  159.   
  160.             // Note: hLen, dkLen, l, r, T, F, etc. are horrible names for  
  161.             //       variables and functions in this day and age, but they  
  162.             //       reflect the terse symbols used in RFC 2898 to describe  
  163.             //       the PBKDF2 algorithm, which improves validation of the  
  164.             //       code vs. the RFC.  
  165.             //  
  166.             // dklen is expressed in bytes. (16 for a 128-bit key)  
  167.   
  168.             int hLen = prf.getMacLength();   // 20 for SHA1  
  169.             int l = Math.max(dkLen, hLen);  //  1 for 128bit (16-byte) keys  
  170.             int r = dkLen - (l-1)*hLen;      // 16 for 128bit (16-byte) keys  
  171.             byte T[] = new byte[l * hLen];  
  172.             int ti_offset = 0;  
  173.             for (int i = 1; i <= l; i++) {  
  174.                 F(T, ti_offset, prf, salt, iterationCount, i);  
  175.                 ti_offset += hLen;  
  176.             }  
  177.   
  178.             if (r < hLen) {  
  179.                 // Incomplete last block  
  180.                 byte DK[] = new byte[dkLen];  
  181.                 System.arraycopy(T, 0, DK, 0, dkLen);  
  182.                 return DK;  
  183.             }  
  184.             return T;  
  185.         }   
  186.   
  187.         private static void F(byte[] dest, int offset, Mac prf, byte[] S, int c, int blockIndex)   
  188.         {  
  189.             final int hLen = prf.getMacLength();  
  190.             byte U_r[] = new byte[ hLen ];  
  191.             // U0 = S || INT (i);  
  192.             byte U_i[] = new byte[S.length + 4];  
  193.             System.arraycopy(S, 0, U_i, 0, S.length);  
  194.             INT(U_i, S.length, blockIndex);  
  195.             for(int i = 0; i < c; i++) {  
  196.                 U_i = prf.doFinal(U_i);  
  197.                 xor( U_r, U_i );  
  198.             }  
  199.   
  200.             System.arraycopy(U_r, 0, dest, offset, hLen);  
  201.         }  
  202.   
  203.         private static void xor(byte[] dest, byte[] src)   
  204.         {  
  205.             for(int i = 0; i < dest.length; i++) {  
  206.                 dest[i] ^= src[i];  
  207.             }  
  208.         }  
  209.   
  210.         private static void INT(byte[] dest, int offset, int i)   
  211.         {  
  212.             dest[offset + 0] = (byte) (i / (256 * 256 * 256));  
  213.             dest[offset + 1] = (byte) (i / (256 * 256));  
  214.             dest[offset + 2] = (byte) (i / (256));  
  215.             dest[offset + 3] = (byte) (i);  
  216.         }   
  217.   
  218.         // Costructor  
  219.         private PBKDF2 () {}  
  220.   
  221.     }  
  222.       
  223.     /* 
  224.      * HASH 
  225.      */  
  226.     public class HASH   
  227.     {  
  228.           public String MD2(String message) throws NoSuchAlgorithmException   
  229.           {  
  230.                 MessageDigest md2 = MessageDigest.getInstance("MD2");  
  231.                 byte[] array = md2.digest(message.getBytes());  
  232.                 return arrayToString(array);  
  233.           }  
  234.           
  235.           public String MD5(String message) throws NoSuchAlgorithmException   
  236.           {  
  237.                 MessageDigest md5 = MessageDigest.getInstance("MD5");  
  238.                 byte[] array = md5.digest(message.getBytes());  
  239.                 return arrayToString(array);  
  240.           }  
  241.             
  242.           public String SHA1(String message) throws NoSuchAlgorithmException   
  243.           {               
  244.                 MessageDigest sha1 = MessageDigest.getInstance("SHA-1");          
  245.                 byte[] array = sha1.digest(message.getBytes());  
  246.                 return arrayToString(array);                  
  247.           }  
  248.             
  249.           public String SHA256(String message) throws NoSuchAlgorithmException   
  250.           {               
  251.                 MessageDigest sha256 = MessageDigest.getInstance("SHA-256");          
  252.                 byte[] array = sha256.digest(message.getBytes());  
  253.                 return arrayToString(array);                  
  254.           }  
  255.             
  256.           public String SHA384(String message) throws NoSuchAlgorithmException   
  257.           {               
  258.                 MessageDigest sha384 = MessageDigest.getInstance("SHA-384");          
  259.                 byte[] array = sha384.digest(message.getBytes());  
  260.                 return arrayToString(array);                  
  261.           }  
  262.             
  263.           public String SHA512(String message) throws NoSuchAlgorithmException   
  264.           {               
  265.                 MessageDigest sha512 = MessageDigest.getInstance("SHA-512");          
  266.                 byte[] array = sha512.digest(message.getBytes());  
  267.                 return arrayToString(array);                  
  268.           }  
  269.             
  270.           private String arrayToString(byte[] array)   
  271.           {               
  272.                 StringBuffer sb = new StringBuffer();  
  273.                 for (int i = 0; i < array.length; ++i) {  
  274.                   sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3));  
  275.                 }  
  276.                 return sb.toString();                 
  277.           }  
  278.     }  
  279.       
  280.     /* 
  281.      * RSA 
  282.      */  
  283.     public class RSA   
  284.     {  
  285.            private Charset PLAIN_TEXT_ENCODING = Charset.forName("UTF-8");  
  286.            private int KEY_SIZE_BITS = 1024;  
  287.   
  288.            private Key publicKey;  
  289.            private Key privateKey;  
  290.            private BigInteger modulus;  
  291.            private BigInteger exponent;  
  292.            Cipher cipher;  
  293.            KeyFactory fact;  
  294.              
  295.            public RSA()   
  296.                    throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException,   
  297.                    UnsupportedEncodingException, InvalidKeyException   
  298.            {  
  299.                 cipher = Cipher.getInstance("RSA");  
  300.                 fact = KeyFactory.getInstance("RSA");  
  301.                 setNewKey(KEY_SIZE_BITS);  
  302.            }  
  303.              
  304.            public boolean setNewKey(int KeySize)   
  305.                    throws NoSuchAlgorithmException, InvalidKeySpecException  
  306.            {  
  307.                if (KeySize <= 0return false;  
  308.                KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");  
  309.                kpg.initialize(KeySize);  
  310.                KeyPair kp = kpg.genKeyPair();  
  311.                publicKey = kp.getPublic();  
  312.                privateKey = kp.getPrivate();  
  313.                  
  314.                RSAPublicKeySpec pub = (RSAPublicKeySpec) fact.getKeySpec(publicKey, RSAPublicKeySpec.class);  
  315.                modulus = pub.getModulus();  
  316.                exponent = pub.getPublicExponent();  
  317.                  
  318.               return true;  
  319.            }  
  320.              
  321.            public BigInteger getModulus()  
  322.            {  
  323.                return modulus;  
  324.            }  
  325.              
  326.            public BigInteger getExponent()  
  327.            {  
  328.                return exponent;  
  329.            }  
  330.              
  331.            public Key getPublicKey()  
  332.            {  
  333.                return publicKey;  
  334.            }  
  335.              
  336.            public Key getPrivateKey()  
  337.            {  
  338.                return privateKey;  
  339.            }  
  340.              
  341.            public String encrypt(String plaintext)   
  342.                    throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException  
  343.            {  
  344.                  if (plaintext.length() == 0return null;  
  345.                  cipher.init(Cipher.ENCRYPT_MODE, publicKey);  
  346.                  byte[] encrypted = cipher.doFinal(plaintext.getBytes());  
  347.                  return Utils.byteArrayToBase64String(encrypted);  
  348.            }  
  349.              
  350.            public String decrypt(String ciphertext)   
  351.                    throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException   
  352.            {  
  353.                  if (ciphertext.length() == 0return null;  
  354.                  byte[] dec = Utils.base64StringToByteArray(ciphertext);  
  355.                  cipher.init(Cipher.DECRYPT_MODE, privateKey);  
  356.                  byte[] decrypted = cipher.doFinal(dec);  
  357.                  return new String(decrypted, PLAIN_TEXT_ENCODING);  
  358.            }         
  359.     }  
  360.       
  361.     /* 
  362.      * Utils 
  363.      */  
  364.     public static class Utils   
  365.     {  
  366.         public static String pbkdf2(String password, String salt, int iterationCount, int dkLen)   
  367.                 throws InvalidKeyException, NoSuchAlgorithmException   
  368.         {  
  369.             if (dkLen!=16 && dkLen!=24 && dkLen!=32) { dkLen=16; }  
  370.             if (iterationCount<0) { iterationCount=0; }  
  371.               
  372.             byte[] _password = password.getBytes();  
  373.             byte[] _salt = salt.getBytes();  
  374.             byte[] key = PBKDF2.deriveKey(_password, _salt, iterationCount, dkLen);  
  375.             return new String(key);  
  376.         }  
  377.   
  378.         public static byte[] getRandomBytes(int len)  
  379.         {  
  380.             if(len<0) { len=8; }  
  381.             Random ranGen = new SecureRandom();  
  382.             byte[] aesKey = new byte[len];   
  383.             ranGen.nextBytes(aesKey);  
  384.             return aesKey;  
  385.         }  
  386.              
  387.         public static String byteArrayToHexString(byte[] raw)   
  388.         {  
  389.             StringBuilder sb = new StringBuilder(2 + raw.length * 2);  
  390.             sb.append("0x");  
  391.             for (int i = 0; i < raw.length; i++) {  
  392.                 sb.append(String.format("%02X", Integer.valueOf(raw[i] & 0xFF)));  
  393.             }  
  394.             return sb.toString();  
  395.         }  
  396.   
  397.         public static byte[] hexStringToByteArray(String hex)   
  398.         {  
  399.             Pattern replace = Pattern.compile("^0x");  
  400.             String s = replace.matcher(hex).replaceAll("");  
  401.   
  402.             byte[] b = new byte[s.length() / 2];  
  403.             for (int i = 0; i < b.length; i++){  
  404.               int index = i * 2;  
  405.               int v = Integer.parseInt(s.substring(index, index + 2), 16);  
  406.               b[i] = (byte)v;  
  407.             }  
  408.             return b;  
  409.         }  
  410.           
  411.         public static String byteArrayToBase64String(byte[] raw)   
  412.         {  
  413.             return new String(Base64Coder.encode(raw));  
  414.         }  
  415.           
  416.         public static byte[] base64StringToByteArray(String str)   
  417.         {  
  418.             return Base64Coder.decode(str);  
  419.         }  
  420.           
  421.         public static String base64_encode(String str)  
  422.         {  
  423.             return Base64Coder.encodeString(str);  
  424.         }  
  425.           
  426.         public static String base64_decode(String str)  
  427.         {  
  428.             return Base64Coder.decodeString(str);  
  429.         }  
  430.     }  
  431.       
  432.     /* 
  433.      * Base64Coder 
  434.      */  
  435.     private static class Base64Coder   
  436.     {  
  437.         // The line separator string of the operating system.  
  438.         private static final String systemLineSeparator = System.getProperty("line.separator");  
  439.   
  440.         // Mapping table from 6-bit nibbles to Base64 characters.  
  441.         private static final char[] map1 = new char[64];  
  442.         static {  
  443.           int i=0;  
  444.           for (char c='A'; c<='Z'; c++) map1[i++] = c;  
  445.           for (char c='a'; c<='z'; c++) map1[i++] = c;  
  446.           for (char c='0'; c<='9'; c++) map1[i++] = c;  
  447.           map1[i++] = '+'; map1[i++] = '/';   
  448.         }  
  449.   
  450.         // Mapping table from Base64 characters to 6-bit nibbles.  
  451.         private static final byte[] map2 = new byte[128];  
  452.         static {  
  453.           for (int i=0; i<map2.length; i++) map2[i] = -1;  
  454.           for (int i=0; i<64; i++) map2[map1[i]] = (byte)i;   
  455.         }  
  456.   
  457.         /** 
  458.         * Encodes a string into Base64 format. 
  459.         * No blanks or line breaks are inserted. 
  460.         * @param s  A String to be encoded. 
  461.         * @return   A String containing the Base64 encoded data. 
  462.         */  
  463.         public static String encodeString (String s)   
  464.         {  
  465.            return new String(encode(s.getBytes()));   
  466.         }  
  467.   
  468.         /** 
  469.         * Encodes a byte array into Base 64 format and breaks the output into lines of 76 characters. 
  470.         * This method is compatible with <code>sun.misc.BASE64Encoder.encodeBuffer(byte[])</code>. 
  471.         * @param in  An array containing the data bytes to be encoded. 
  472.         * @return    A String containing the Base64 encoded data, broken into lines. 
  473.         */  
  474.         public static String encodeLines (byte[] in)   
  475.         {  
  476.            return encodeLines(in, 0, in.length, 76, systemLineSeparator);   
  477.         }  
  478.   
  479.         /** 
  480.         * Encodes a byte array into Base 64 format and breaks the output into lines. 
  481.         * @param in            An array containing the data bytes to be encoded. 
  482.         * @param iOff          Offset of the first byte in <code>in</code> to be processed. 
  483.         * @param iLen          Number of bytes to be processed in <code>in</code>, starting at <code>iOff</code>. 
  484.         * @param lineLen       Line length for the output data. Should be a multiple of 4. 
  485.         * @param lineSeparator The line separator to be used to separate the output lines. 
  486.         * @return              A String containing the Base64 encoded data, broken into lines. 
  487.         */  
  488.         public static String encodeLines (byte[] in, int iOff, int iLen, int lineLen, String lineSeparator)   
  489.         {  
  490.            int blockLen = (lineLen*3) / 4;  
  491.            if (blockLen <= 0throw new IllegalArgumentException();  
  492.            int lines = (iLen+blockLen-1) / blockLen;  
  493.            int bufLen = ((iLen+2)/3)*4 + lines*lineSeparator.length();  
  494.            StringBuilder buf = new StringBuilder(bufLen);  
  495.            int ip = 0;  
  496.            while (ip < iLen)   
  497.            {  
  498.               int l = Math.min(iLen-ip, blockLen);  
  499.               buf.append (encode(in, iOff+ip, l));  
  500.               buf.append (lineSeparator);  
  501.               ip += l;   
  502.            }  
  503.            return buf.toString();   
  504.         }  
  505.   
  506.         /** 
  507.         * Encodes a byte array into Base64 format. 
  508.         * No blanks or line breaks are inserted in the output. 
  509.         * @param in  An array containing the data bytes to be encoded. 
  510.         * @return    A character array containing the Base64 encoded data. 
  511.         */  
  512.         public static char[] encode (byte[] in)   
  513.         {  
  514.            return encode(in, 0, in.length);   
  515.         }  
  516.   
  517.         /** 
  518.         * Encodes a byte array into Base64 format. 
  519.         * No blanks or line breaks are inserted in the output. 
  520.         * @param in    An array containing the data bytes to be encoded. 
  521.         * @param iLen  Number of bytes to process in <code>in</code>. 
  522.         * @return      A character array containing the Base64 encoded data. 
  523.         */  
  524.         public static char[] encode (byte[] in, int iLen)   
  525.         {  
  526.            return encode(in, 0, iLen);   
  527.         }  
  528.   
  529.         /** 
  530.         * Encodes a byte array into Base64 format. 
  531.         * No blanks or line breaks are inserted in the output. 
  532.         * @param in    An array containing the data bytes to be encoded. 
  533.         * @param iOff  Offset of the first byte in <code>in</code> to be processed. 
  534.         * @param iLen  Number of bytes to process in <code>in</code>, starting at <code>iOff</code>. 
  535.         * @return      A character array containing the Base64 encoded data. 
  536.         */  
  537.         public static char[] encode (byte[] in, int iOff, int iLen)   
  538.         {  
  539.            int oDataLen = (iLen*4+2)/3;       // output length without padding  
  540.            int oLen = ((iLen+2)/3)*4;         // output length including padding  
  541.            char[] out = new char[oLen];  
  542.            int ip = iOff;  
  543.            int iEnd = iOff + iLen;  
  544.            int op = 0;  
  545.            while (ip < iEnd)   
  546.            {  
  547.               int i0 = in[ip++] & 0xff;  
  548.               int i1 = ip < iEnd ? in[ip++] & 0xff : 0;  
  549.               int i2 = ip < iEnd ? in[ip++] & 0xff : 0;  
  550.               int o0 = i0 >>> 2;  
  551.               int o1 = ((i0 &   3) << 4) | (i1 >>> 4);  
  552.               int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);  
  553.               int o3 = i2 & 0x3F;  
  554.               out[op++] = map1[o0];  
  555.               out[op++] = map1[o1];  
  556.               out[op] = op < oDataLen ? map1[o2] : '='; op++;  
  557.               out[op] = op < oDataLen ? map1[o3] : '='; op++;   
  558.            }  
  559.            return out;   
  560.         }  
  561.   
  562.         /** 
  563.         * Decodes a string from Base64 format. 
  564.         * No blanks or line breaks are allowed within the Base64 encoded input data. 
  565.         * @param s  A Base64 String to be decoded. 
  566.         * @return   A String containing the decoded data. 
  567.         * @throws   IllegalArgumentException If the input is not valid Base64 encoded data. 
  568.         */  
  569.         public static String decodeString (String s)   
  570.         {  
  571.            return new String(decode(s));   
  572.         }  
  573.   
  574.         /** 
  575.         * Decodes a byte array from Base64 format and ignores line separators, tabs and blanks. 
  576.         * CR, LF, Tab and Space characters are ignored in the input data. 
  577.         * This method is compatible with <code>sun.misc.BASE64Decoder.decodeBuffer(String)</code>. 
  578.         * @param s  A Base64 String to be decoded. 
  579.         * @return   An array containing the decoded data bytes. 
  580.         * @throws   IllegalArgumentException If the input is not valid Base64 encoded data. 
  581.         */  
  582.         public static byte[] decodeLines (String s)   
  583.         {  
  584.            char[] buf = new char[s.length()];  
  585.            int p = 0;  
  586.            for (int ip = 0; ip < s.length(); ip++) {  
  587.               char c = s.charAt(ip);  
  588.               if (c != ' ' && c != '\r' && c != '\n' && c != '\t')  
  589.                  buf[p++] = c;   
  590.            }  
  591.            return decode(buf, 0, p);   
  592.         }  
  593.   
  594.         /** 
  595.         * Decodes a byte array from Base64 format. 
  596.         * No blanks or line breaks are allowed within the Base64 encoded input data. 
  597.         * @param s  A Base64 String to be decoded. 
  598.         * @return   An array containing the decoded data bytes. 
  599.         * @throws   IllegalArgumentException If the input is not valid Base64 encoded data. 
  600.         */  
  601.         public static byte[] decode (String s)   
  602.         {  
  603.            return decode(s.toCharArray());   
  604.         }  
  605.   
  606.         /** 
  607.         * Decodes a byte array from Base64 format. 
  608.         * No blanks or line breaks are allowed within the Base64 encoded input data. 
  609.         * @param in  A character array containing the Base64 encoded data. 
  610.         * @return    An array containing the decoded data bytes. 
  611.         * @throws    IllegalArgumentException If the input is not valid Base64 encoded data. 
  612.         */  
  613.         public static byte[] decode (char[] in)   
  614.         {  
  615.            return decode(in, 0, in.length);   
  616.         }  
  617.   
  618.         /** 
  619.         * Decodes a byte array from Base64 format. 
  620.         * No blanks or line breaks are allowed within the Base64 encoded input data. 
  621.         * @param in    A character array containing the Base64 encoded data. 
  622.         * @param iOff  Offset of the first character in <code>in</code> to be processed. 
  623.         * @param iLen  Number of characters to process in <code>in</code>, starting at <code>iOff</code>. 
  624.         * @return      An array containing the decoded data bytes. 
  625.         * @throws      IllegalArgumentException If the input is not valid Base64 encoded data. 
  626.         */  
  627.         public static byte[] decode (char[] in, int iOff, int iLen)   
  628.         {  
  629.            if (iLen%4 != 0throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4.");  
  630.            while (iLen > 0 && in[iOff+iLen-1] == '=') iLen--;  
  631.            int oLen = (iLen*3) / 4;  
  632.            byte[] out = new byte[oLen];  
  633.            int ip = iOff;  
  634.            int iEnd = iOff + iLen;  
  635.            int op = 0;  
  636.            while (ip < iEnd)   
  637.            {  
  638.               int i0 = in[ip++];  
  639.               int i1 = in[ip++];  
  640.               int i2 = ip < iEnd ? in[ip++] : 'A';  
  641.               int i3 = ip < iEnd ? in[ip++] : 'A';  
  642.               if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)  
  643.                  throw new IllegalArgumentException ("Illegal character in Base64 encoded data.");  
  644.               int b0 = map2[i0];  
  645.               int b1 = map2[i1];  
  646.               int b2 = map2[i2];  
  647.               int b3 = map2[i3];  
  648.               if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0)  
  649.                  throw new IllegalArgumentException ("Illegal character in Base64 encoded data.");  
  650.               int o0 = ( b0       <<2) | (b1>>>4);  
  651.               int o1 = ((b1 & 0xf)<<4) | (b2>>>2);  
  652.               int o2 = ((b2 &   3)<<6) |  b3;  
  653.               out[op++] = (byte)o0;  
  654.               if (op<oLen) out[op++] = (byte)o1;  
  655.               if (op<oLen) out[op++] = (byte)o2;   
  656.            }  
  657.            return out;   
  658.         }  
  659.   
  660.         // Dummy constructor.  
  661.         private Base64Coder() {}  
  662.     }  
  663. }  

The modes of operation currently available are: