第十一篇: JAVA加密解密之Base64

本文介绍了Base64编码的基本原理及其实现方法,并通过一个Java示例展示了如何进行Base64编码与解码操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

package com.jianggujin.codec;

/**
 * Base64
 * 
 * @author jianggujin
 *
 */
public class HQBase64
{
   private final byte[] EMPTY = new byte[0];
   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 byte[] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];

   private static HQBase64 base64 = new HQBase64();

   public static HQBase64 getInstance()
   {
      return base64;
   }

   private HQBase64()
   {
      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] = (byte) ('A' + i);
      }

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

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

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

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

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

   private int removeWhiteSpace(byte[] 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 byte[] encode(byte[] binaryData)
   {
      if (binaryData == null)
      {
         return null;
      }

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

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

      encodedData = new byte[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 encodedData;
   }

   public byte[] decode(byte[] encoded)
   {
      if (encoded == null)
      {
         return null;
      }

      byte[] base64Data = encoded;
      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;
      byte 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;
   }

   public String encodeToString(byte[] binaryData)
   {
      return new String(encode(binaryData));
   }

   public String encodeToString(String data)
   {
      return new String(encode(data.getBytes()));
   }

   public byte[] decodeString(String encoded)
   {
      return decode(encoded.getBytes());
   }
}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293

编写一个测试类来测试一下:

import org.junit.Test;

import com.jianggujin.codec.HQBase64;

public class Base64Test
{
   HQBase64 base64 = HQBase64.getInstance();

   @Test
   public void encode()
   {
      byte[] data = "jianggujin".getBytes();
      String result = base64.encodeToString(data);
      System.err.println(result);
      System.err.println(new String(base64.decodeString(result)));
   }
}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

运行结果: 
amlhbmdndWppbg== 
jianggujin

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值