Java 加密算法(一)

個(gè)人博客:haichenyi.com。感謝關(guān)注

補(bǔ)充知識點(diǎn):

字節(jié):也就是 byte 是一種統(tǒng)計(jì)單位,表示數(shù)量的多少

字符:是指計(jì)算機(jī)中使用的文字和符號,比如:1、2、3、A、S、D、$、%等等符號

字節(jié)與字符的對應(yīng)關(guān)系:它們完全不是一個(gè)概念,所以,沒有什么有沒有區(qū)別這個(gè)說法。不同的編碼,兩者的對應(yīng)關(guān)系是不相同的,我這里就說常用的兩種編碼:

  1. ASCII碼中,一個(gè)英文字母(不區(qū)分大小寫)占一個(gè)字節(jié),一個(gè)中文漢字占兩個(gè)字節(jié)
  2. UTF-8中,一個(gè)英文字母占一個(gè)字節(jié),一個(gè)中文漢字占三個(gè)字節(jié)

??我們加密最終常常操作的是bit,而我們加密首先得到的是byte數(shù)組的,byte的取值范圍-128~127,中間包括0,剛好256個(gè)。也就是2^8=256。并且,1 byte = 8 bit(1kb = 1024 byte = 8^1024 bit等等)

??我們獲得了byte之后,要把byte數(shù)組轉(zhuǎn)成String字符串,String其實(shí)就是char數(shù)組,我們java有一個(gè)new String(char[] chars),應(yīng)該都用過。我們轉(zhuǎn)成字符串的前提是轉(zhuǎn)成char數(shù)組,由于,1 char = 2 byte,所以,我們byte轉(zhuǎn)成char長度擴(kuò)大了1倍。

四種分類

  1. MD5加密
  2. Base64加密
  3. 對稱加密
  4. 非對稱加密

MD5加密——不可逆

概念

??MD5加密是我們常見的加密算法,是不可逆的,也就是說加密完成之后,無法解密轉(zhuǎn)成原來的內(nèi)容。MD5加密算法其實(shí)是一種散列函數(shù),使用的是hash算法。MD5的原文是無線多個(gè),但是MD5的值是有限的。所以一個(gè)MD5的值可能對應(yīng)多個(gè)原文。SHA算法跟MD5是差不多的,只是MD5是128位,SHA是160位,多32位

??為什么MD5的值是有限多個(gè)呢?主流的MD5使用的是將任意長度的字節(jié)串映射為一個(gè)128bit的大整數(shù)。也就是一共有2^128種可能,所以說這個(gè)數(shù)字是有限的,而,我們的原文則是無限多個(gè)。發(fā)現(xiàn)兩段原文對應(yīng)同一個(gè)MD5的值概率非常小,也就忽略不記了。

使用

String name1 = "haichenyi";
   String name2 = "海晨憶";
    try {
      MessageDigest md5 = MessageDigest.getInstance("MD5");
      byte[] digest1 = md5.digest(name1.getBytes("UTF-8"));
      Log.v("WZ","length1:"+digest1.length);

      byte[] digest2 = md5.digest(name2.getBytes("UTF-8"));
      Log.v("WZ","length1:"+digest2.length);
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }

??我們通過MD5,得到的是一個(gè)byte數(shù)組(這個(gè)byte數(shù)組的長度跟我們的1byte=8bit沒有直接關(guān)系),我們需要做的就是對這個(gè)byte數(shù)組進(jìn)行操作,我們習(xí)慣上就是把這個(gè)btye轉(zhuǎn)成16進(jìn)制數(shù)存進(jìn)數(shù)據(jù)庫,當(dāng)然,你也可以轉(zhuǎn)成其他的類型存到數(shù)據(jù)庫。這里給出幾個(gè)byte數(shù)組轉(zhuǎn)16進(jìn)制字符串的方法,親測可用:

private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5',
      '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

  /**
   * 方法一:
   * byte[] to hex string
   *
   * @param bytes
   * @return
   */
  public String bytesToHexFun1(byte[] bytes) {
    // 一個(gè)byte為8位,可用兩個(gè)十六進(jìn)制位標(biāo)識
    char[] buf = new char[bytes.length * 2];
    int a = 0;
    int index = 0;
    for (byte b : bytes) { // 使用除與取余進(jìn)行轉(zhuǎn)換
      if (b < 0) {
        a = 256 + b;
      } else {
        a = b;
      }
      buf[index++] = HEX_CHAR[a / 16];
      buf[index++] = HEX_CHAR[a % 16];
    }
    return new String(buf);
  }
  
  /**
   * 方法二:
   * byte[] to hex string
   *
   * @param bytes
   * @return
   */
  public String bytesToHexFun2(byte[] bytes) {
    char[] buf = new char[bytes.length * 2];
    int index = 0;
    for(byte b : bytes) { // 利用位運(yùn)算進(jìn)行轉(zhuǎn)換,可以看作方法一的變種
      buf[index++] = HEX_CHAR[b >>> 4 & 0xf];
      buf[index++] = HEX_CHAR[b & 0xf];
    }

    return new String(buf);
  }
  
  /**
   * 方法三:
   * byte[] to hex string
   *
   * @param bytes
   * @return
   */
  public String bytesToHexFun3(byte[] bytes) {
    StringBuilder buf = new StringBuilder(bytes.length * 2);
    for(byte b : bytes) { // 使用String的format方法進(jìn)行轉(zhuǎn)換
      buf.append(String.format("%02x", new Integer(b & 0xff)));
    }

    return buf.toString();
  }
  
  /**
   * 將16進(jìn)制字符串轉(zhuǎn)換為byte[]
   *
   * @param str
   * @return
   */
  public byte[] toBytes(String str) {
    if(str == null || str.trim().equals("")) {
      return new byte[0];
    }

    byte[] bytes = new byte[str.length() / 2];
    for(int i = 0; i < str.length() / 2; i++) {
      String subStr = str.substring(i * 2, i * 2 + 2);
      bytes[i] = (byte) Integer.parseInt(subStr, 16);
    }

    return bytes;
  }

Base64加密——可逆

流程

  1. 要知道的是有一個(gè)64個(gè)數(shù)的表,也稱Base64編碼表??梢宰止?jié)定義,不過都是用的一樣的。
  2. Base64是按照字符長度,以3個(gè)字符為一組
  3. 接著增對每組的每個(gè)字符,取ASCII編碼
  4. 然后將獲得的編碼轉(zhuǎn)換成8bit的二進(jìn)制,就會得到3*8=24bit的字節(jié)
  5. 然后將這24bit的字節(jié)以6個(gè)bit為一組,分成4組
  6. 接著在每組前面填兩個(gè)高位0,湊成每組8bit
  7. 最后將這每組8bit的二進(jìn)制轉(zhuǎn)成十進(jìn)制,對應(yīng)下面的Base64編碼表

Base64 編碼表

value char value char value char value char
0 A 16 Q 32 g 48 w
1 B 17 R 33 h 49 x
2 C 18 S 34 i 50 y
3 D 19 T 35 j 51 z
4 E 20 U 36 k 52 0
5 F 21 V 37 l 53 1
6 G 22 U 38 m 54 2
7 H 23 X 39 n 55 3
8 I 24 Y 40 o 56 4
9 J 25 Z 41 p 57 5
10 K 26 a 42 q 58 6
11 L 27 b 43 r 59 7
12 M 28 c 44 s 60 8
13 N 29 d 45 t 61 9
14 O 30 e 46 u 62 +
15 P 31 f 47 v 63 /

使用

String str = "hai";
    byte[] encode = Base64.encode(str.getBytes(), Base64.NO_WRAP);
    try {
      String a = new String(encode,"UTF-8");
      String a1 = new String(encode,"US-ASCII");
      Log.v("wz",a);
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }
    String after = Base64.encodeToString(str.getBytes(), Base64.NO_WRAP);
    Log.v("wz","after-->"+after);

解析

??這里,我要使用Base64加密"hai"這個(gè)字符串,根據(jù)上面的流程:

待加密字符串 h a i
ASCII編碼 104 97 105
二進(jìn)制 01101000 01100001 01101001

下面,上面的表不好表示,我再換一個(gè)表,下一步,該6位分一組了

現(xiàn)在的字符串:01101000 01100001 01101001

六位分一組 011010 000110 000101 101001
每組前面補(bǔ)0 00011010 00000110 00000101 00101001
轉(zhuǎn)成10進(jìn)制 26 6 5 41
Base64編碼 a G F p

結(jié)果圖:

PS:

  1. Base64.encodeToString()方法直接轉(zhuǎn)成加密后的字符串
  2. Base64.encode()方法返回的byte數(shù)組是16進(jìn)制的,不用手動在去轉(zhuǎn)一遍16進(jìn)制
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 概述 之前一直對加密相關(guān)的算法知之甚少,只知道類似DES、RSA等加密算法能對數(shù)據(jù)傳輸進(jìn)行加密,且各種加密算法各有...
    Henryzhu閱讀 3,208評論 0 14
  • 編碼問題一直困擾著開發(fā)人員,尤其在 Java 中更加明顯,因?yàn)?Java 是跨平臺語言,不同平臺之間編碼之間的切換...
    x360閱讀 2,579評論 1 20
  • 通宵復(fù)習(xí)是因?yàn)槠綍r(shí)沒有努力學(xué)習(xí),拼命減肥是因?yàn)槌粤闶硰膩聿粫刂?,分手了才開始后悔是因?yàn)橹安欢?..
    安然的小寶閱讀 245評論 0 0
  • 不能迷失,不能忘,法則就是這樣,誰都會離開你的,除非你夠強(qiáng)
    沒帶蘑菇的提莫閱讀 246評論 0 0
  • 昨天晚上回家讀了三毛的書,說實(shí)話,這本書我拿起來看過好多次,沒有一次能看進(jìn)去過,每次僅僅只是眼睛在讀,看過之后完全...
    私人標(biāo)簽zx閱讀 205評論 0 1

友情鏈接更多精彩內(nèi)容