JAVA加密解密之Base64

Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。Base64编码可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。

package com.hq.coder;

/**
 * Base64加密解密类
 *
 * @author jianggujin
 *
 */
public class Base64
{
   private final int BASELENGTH = 128;
   private final int LOOKUPLENGTH = 64;
   private final int TWENTYFOURBITGROUP = 24;
   private final int EIGHTBIT = 8;
   private final int SIXTEENBIT = 16;
   private final int FOURBYTE = 4;
   private final int SIGN = -128;
   private final char PAD = '=';
   private final byte[] base64Alphabet = new byte[BASELENGTH];
   private final char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];

   public Base64()
   {
      for (int i = 0; i < BASELENGTH; ++i)
      {
         base64Alphabet[i] = -1;
      }
      for (int i = 'Z'; i >= 'A'; i--)
      {
         base64Alphabet[i] = (byte) (i - 'A');
      }
      for (int i = 'z'; i >= 'a'; i--)
      {
         base64Alphabet[i] = (byte) (i - 'a' + 26);
      }

      for (int i = '9'; i >= '0'; i--)
      {
         base64Alphabet[i] = (byte) (i - '0' + 52);
      }

      base64Alphabet['+'] = 62;
      base64Alphabet['/'] = 63;

      for (int i = 0; i <= 25; i++)
      {
         lookUpBase64Alphabet[i] = (char) ('A' + i);
      }

      for (int i = 26, j = 0; i <= 51; i++, j++)
      {
         lookUpBase64Alphabet[i] = (char) ('a' + j);
      }

      for (int i = 52, j = 0; i <= 61; i++, j++)
      {
         lookUpBase64Alphabet[i] = (char) ('0' + j);
      }
      lookUpBase64Alphabet[62] = (char) '+';
      lookUpBase64Alphabet[63] = (char) '/';
   }

   private boolean isWhiteSpace(char octect)
   {
      return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
   }

   private boolean isPad(char octect)
   {
      return (octect == PAD);
   }

   private boolean isData(char octect)
   {
      return (octect < BASELENGTH && base64Alphabet[octect] != -1);
   }

   /**
    * 编码
    *
    * @param binaryData
    * @return
    */
   public String encode(byte[] binaryData)
   {

      if (binaryData == null)
      {
         return null;
      }

      int lengthDataBits = binaryData.length * EIGHTBIT;
      if (lengthDataBits == 0)
      {
         return "";
      }

      int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
      int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
      int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1
            : numberTriplets;
      char encodedData[] = null;

      encodedData = new char[numberQuartet * 4];

      byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;

      int encodedIndex = 0;
      int dataIndex = 0;

      for (int i = 0; i < numberTriplets; i++)
      {
         b1 = binaryData[dataIndex++];
         b2 = binaryData[dataIndex++];
         b3 = binaryData[dataIndex++];

         l = (byte) (b2 & 0x0f);
         k = (byte) (b1 & 0x03);

         byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
               : (byte) ((b1) >> 2 ^ 0xc0);
         byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
               : (byte) ((b2) >> 4 ^ 0xf0);
         byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6)
               : (byte) ((b3) >> 6 ^ 0xfc);

         encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
         encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
         encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
         encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
      }

      if (fewerThan24bits == EIGHTBIT)
      {
         b1 = binaryData[dataIndex];
         k = (byte) (b1 & 0x03);
         byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
               : (byte) ((b1) >> 2 ^ 0xc0);
         encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
         encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
         encodedData[encodedIndex++] = PAD;
         encodedData[encodedIndex++] = PAD;
      }
      else if (fewerThan24bits == SIXTEENBIT)
      {
         b1 = binaryData[dataIndex];
         b2 = binaryData[dataIndex + 1];
         l = (byte) (b2 & 0x0f);
         k = (byte) (b1 & 0x03);

         byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
               : (byte) ((b1) >> 2 ^ 0xc0);
         byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
               : (byte) ((b2) >> 4 ^ 0xf0);

         encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
         encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
         encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
         encodedData[encodedIndex++] = PAD;
      }

      return new String(encodedData);
   }

   /**
    * 解码
    *
    * @param encoded
    * @return
    */
   public byte[] decode(String encoded)
   {

      if (encoded == null)
      {
         return null;
      }

      char[] base64Data = encoded.toCharArray();
      int len = removeWhiteSpace(base64Data);

      if (len % FOURBYTE != 0)
      {
         return null;
      }

      int numberQuadruple = (len / FOURBYTE);

      if (numberQuadruple == 0)
      {
         return new byte[0];
      }

      byte decodedData[] = null;
      byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
      char d1 = 0, d2 = 0, d3 = 0, d4 = 0;

      int i = 0;
      int encodedIndex = 0;
      int dataIndex = 0;
      decodedData = new byte[(numberQuadruple) * 3];

      for (; i < numberQuadruple - 1; i++)
      {

         if (!isData((d1 = base64Data[dataIndex++]))
               || !isData((d2 = base64Data[dataIndex++]))
               || !isData((d3 = base64Data[dataIndex++]))
               || !isData((d4 = base64Data[dataIndex++])))
         {
            return null;
         }

         b1 = base64Alphabet[d1];
         b2 = base64Alphabet[d2];
         b3 = base64Alphabet[d3];
         b4 = base64Alphabet[d4];

         decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
         decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
         decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
      }

      if (!isData((d1 = base64Data[dataIndex++]))
            || !isData((d2 = base64Data[dataIndex++])))
      {
         return null;// if found "no data" just return null
      }

      b1 = base64Alphabet[d1];
      b2 = base64Alphabet[d2];

      d3 = base64Data[dataIndex++];
      d4 = base64Data[dataIndex++];
      if (!isData((d3)) || !isData((d4)))
      {
         if (isPad(d3) && isPad(d4))
         {
            if ((b2 & 0xf) != 0)
            {
               return null;
            }
            byte[] tmp = new byte[i * 3 + 1];
            System.arraycopy(decodedData, 0, tmp, 0, i * 3);
            tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
            return tmp;
         }
         else if (!isPad(d3) && isPad(d4))
         {
            b3 = base64Alphabet[d3];
            if ((b3 & 0x3) != 0)// last 2 bits should be zero
            {
               return null;
            }
            byte[] tmp = new byte[i * 3 + 2];
            System.arraycopy(decodedData, 0, tmp, 0, i * 3);
            tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
            tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
            return tmp;
         }
         else
         {
            return null;
         }
      }
      else
      {
         b3 = base64Alphabet[d3];
         b4 = base64Alphabet[d4];
         decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
         decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
         decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);

      }

      return decodedData;
   }

   private int removeWhiteSpace(char[] data)
   {
      if (data == null)
      {
         return 0;
      }

      int newSize = 0;
      int len = data.length;
      for (int i = 0; i < len; i++)
      {
         if (!isWhiteSpace(data[i]))
         {
            data[newSize++] = data[i];
         }
      }
      return newSize;
   }

   public static void main(String[] args)
   {
      String data = "BASE64Demo";
      Base64 base64 = new Base64();
      String encode = base64.encode(data.getBytes());
      System.out.println(encode);
      System.out.println(new String(base64.decode(encode)));
   }
}

运行结果:
QkFTRTY0RGVtbw==
BASE64Demo

时间: 2024-09-11 15:53:45

JAVA加密解密之Base64的相关文章

Java加密解密工具(适用于JavaSE/JavaEE/Android)_java

本文实例为大家分享了一个适用于JavaSE/JavaEE/Android的Java加密解密工具,供大家学习,具体内容如下 package longshu.utils.security; import java.lang.reflect.Method; import java.security.InvalidKeyException; import java.security.Key; import java.security.MessageDigest; import java.security

JAVA加密解密:自定义类加载器应用

最近在研究JAVA CLASS LOADING技术,已实现了一个自定义的加载器.对目前自定义加载器的应用,还在探讨中.下面是自定义的CLASSLOADER在JAVA加密解密方面的一些研究. JAVA安全 JAVA是解释执行的语言,对于不同的操作平台都有相应的JVM对字节码文件进行解释执行.而这个字节码文件,也就是我们平时所看到的每一个.class文件. 这是我们大家都知道的常识,也就是由.java文件,经过编译器编译,变成JVM所能解释的.class文件. 而这个过程,在现在公开的网络技术中,利

Java加密解密

JAVA是解释执行的语言,对于不同的操作平台都有相应的JVM对字节码文件进行解释执行.而这个字节码文件,也就是我们平时所看到的每一个.class文件.这是我们大家都知道的常识,也就是由.java文件,经过编译器编译,变成JVM所能解释的.class文件.而这个过程,在现在公开的网络技术中,利用一个反编译器,任何人都可以很容易的获取它的源文件.这对于很多人来说是不希望看到的.对于加密解密技术,我懂的不多,有些可以利用某种技术"模糊"JAVA类文件.这样能够使反编译的难度增加.但估计反编译

JAVA加密解密之对称加密

写的一个JAVA对称加密的工具类,支持DES.DESede.AES.Blowfish.RC2.RC4的加密解密. DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1976年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),随后在国际上广泛流传开来. DESede是由DES对称加密算法改进后的一种对称加密算法.使用 168 位的密钥对资料进行三次加密的一种机制:它通常(但非始终)提供极其强大的安全性.如果三个 56 位的子元素都

JAVA加密解密之常用签名算法

Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护.该算法的文件号为RFC 1321(R.Rivest,MIT Laboratory for Computer Science and RSA Data Security Inc. April 1992). MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致.是计算机广泛使用的杂凑算法之一(又译

JAVA加密解密之RSA算法

RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的.1987年首次公布,当时他们三人都在麻省理工学院工作.RSA就是他们三人姓氏开头字母拼在一起组成的. RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准. 今天只有短的RSA钥匙才可能被强力方式解破.到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式.只

ArcFour加密解密,java RC4加密解密,java 加密解密

 package com.app.common.util; public class ArcFour { /** * 加密解密 参数为String 字符串(String data, String key) * * @param data * @param key * @return String * @throws UnsupportedEncodingException */ public static final int vactorLen = 256; private static S

JAVA加密解密之DH算法

Diffie-Hellman:一种确保共享KEY安全穿越不安全网络的方法,它是OAKLEY的一个组成部分.Whitfield Diffie与Martin Hellman在1976年提出了一个奇妙的密钥交换协议,称为Diffie-Hellman密钥交换协议/算法(Diffie-Hellman Key Exchange/Agreement Algorithm).这个机制的巧妙在于需要安全通信的双方可以用这个方法确定对称密钥.然后可以用这个密钥进行加密和解密.但是注意,这个密钥交换协议/算法只能用于密

JAVA加密解密之PBE算法

PBE(Password Based Encryption,基于口令加密)是一种基于口令的加密算法,其特点是使用口令代替了密钥,而口令由用户自己掌管,采用随机数杂凑多重加密等方法保证数据的安全性.PBE算法在加密过程中并不是直接使用口令来加密,而是加密的密钥由口令生成,这个功能由PBE算法中的KDF函数完成.KDF函数的实现过程为:将用户输入的口令首先通过"盐"(salt)的扰乱产生准密钥,再将准密钥经过散列函数多次迭代后生成最终加密密钥,密钥生成后,PBE算法再选用对称加密算法对数据