欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android對(duì)稱加密與非對(duì)稱加密

 更新時(shí)間:2016年09月10日 11:01:59   作者:axi295309066  
這篇文章主要為大家詳細(xì)介紹了Android對(duì)稱加密與非對(duì)稱加密,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

凱撒密碼

1. 介紹

凱撒密碼作為一種最為古老的對(duì)稱加密體制,在古羅馬的時(shí)候都已經(jīng)很流行,他的基本思想是:通過把字母移動(dòng)一定的位數(shù)來實(shí)現(xiàn)加密和解密。明文中的所有字母都在字母表上向后(或向前)按照一個(gè)固定數(shù)目進(jìn)行偏移后被替換成密文。例如,當(dāng)偏移量是3 的時(shí)候,所有的字母A 將被替換成D,B 變成E,由此可見,位數(shù)就是凱撒密碼加密和解密的密鑰。

例如:字符串”ABC”的每個(gè)字符都右移3 位則變成”DEF”,解密的時(shí)候”DEF”的每個(gè)字符左移3 位即能還原,如下圖所示:

這里寫圖片描述

2. 準(zhǔn)備知識(shí)

 //字符轉(zhuǎn)換成ASCII 碼數(shù)值
 char charA = 'a';
 int intA = charA; //char 強(qiáng)轉(zhuǎn)為int 即得到對(duì)應(yīng)的ASCII 碼值,'a'的值為97

//ASCII 碼值轉(zhuǎn)成char
int intA = 97;//97 對(duì)應(yīng)的ASCII 碼'a'
char charA = (char) intA; //int 值強(qiáng)轉(zhuǎn)為char 即得到對(duì)應(yīng)的ASCII 字符,即'a'

3. 凱撒密碼的簡(jiǎn)單代碼實(shí)現(xiàn)

 /**
   * 加密
   * @param input 數(shù)據(jù)源(需要加密的數(shù)據(jù))
   * @param key 秘鑰,即偏移量
   * @return 返回加密后的數(shù)據(jù)
   */
  public static String encrypt(String input, int key) {
    //得到字符串里的每一個(gè)字符
    char[] array = input.toCharArray();

    for (int i = 0; i < array.length; ++i) {
      //字符轉(zhuǎn)換成ASCII 碼值
      int ascii = array[i];
      //字符偏移,例如a->b
      ascii = ascii + key;
      //ASCII 碼值轉(zhuǎn)換為char
      char newChar = (char) ascii;
      //替換原有字符
      array[i] = newChar;

      //以上4 行代碼可以簡(jiǎn)寫為一行
      //array[i] = (char) (array[i] + key);
    }

    //字符數(shù)組轉(zhuǎn)換成String
    return new String(array);
  }

  /**
   * 解密
   * @param input 數(shù)據(jù)源(被加密后的數(shù)據(jù))
   * @param key 秘鑰,即偏移量
   * @return 返回解密后的數(shù)據(jù)
   */
  public static String decrypt(String input, int key) {
    //得到字符串里的每一個(gè)字符
    char[] array = input.toCharArray();
    for (int i = 0; i < array.length; ++i) {
      //字符轉(zhuǎn)換成ASCII 碼值
      int ascii = array[i];
      //恢復(fù)字符偏移,例如b->a
      ascii = ascii - key;
      //ASCII 碼值轉(zhuǎn)換為char
      char newChar = (char) ascii;
      //替換原有字符
      array[i] = newChar;

      //以上4 行代碼可以簡(jiǎn)寫為一行
      //array[i] = (char) (array[i] - key);
    }

    //字符數(shù)組轉(zhuǎn)換成String
    return new String(array);
  }

代碼輸出結(jié)果:

這里寫圖片描述

4. 破解凱撒密碼:頻率分析法

凱撒密碼加密強(qiáng)度太低,只需要用頻度分析法即可破解。
在任何一種書面語言中,不同的字母或字母組合出現(xiàn)的頻率各不相同。而且,對(duì)于以這種語言書寫的任意一段文本,都具有大致相同的特征字母分布。比如,在英語中,字母E 出現(xiàn)的頻率很高,而X 則出現(xiàn)得較少。

英語文本中典型的字母分布情況如下圖所示:

這里寫圖片描述

5. 破解流程

統(tǒng)計(jì)密文里出現(xiàn)次數(shù)最多的字符,例如出現(xiàn)次數(shù)最多的字符是是'h'。

計(jì)算字符'h'到'e'的偏移量,值為3,則表示原文偏移了3 個(gè)位置。

將密文所有字符恢復(fù)偏移3 個(gè)位置。

注意點(diǎn):統(tǒng)計(jì)密文里出現(xiàn)次數(shù)最多的字符時(shí),需多統(tǒng)計(jì)幾個(gè)備選,因?yàn)樽疃嗟目赡苁强崭窕蛘咂渌址?,例如下圖出現(xiàn)次數(shù)最多的字符'#'是空格加密后的字符,'h'才是'e'偏移后的值。
這里寫圖片描述

解密時(shí)要多幾次嘗試,因?yàn)椴灰欢ǔ霈F(xiàn)次數(shù)最多的字符就是我們想要的目標(biāo)字符,如下圖,第二次解密的結(jié)果才是正確的。

/**
 * 頻率分析法破解凱撒密碼
 */
public class FrequencyAnalysis {
  //英文里出現(xiàn)次數(shù)最多的字符
  private static final char MAGIC_CHAR = 'e';
  //破解生成的最大文件數(shù)
  private static final int DE_MAX_FILE = 4;

  public static void main(String[] args) throws Exception {
    //測(cè)試1,統(tǒng)計(jì)字符個(gè)數(shù)
    //printCharCount("article1_en.txt");

    //加密文件
    //int key = 3;
    //encryptFile("article1.txt", "article1_en.txt", key);

    //讀取加密后的文件
    String artile = file2String("article1_en.txt");
    //解密(會(huì)生成多個(gè)備選文件)
    decryptCaesarCode(artile, "article1_de.txt");
  }

  public static void printCharCount(String path) throws IOException{
    String data = file2String(path);
    List<Entry<Character, Integer>> mapList = getMaxCountChar(data);
    for (Entry<Character, Integer> entry : mapList) {
      //輸出前幾位的統(tǒng)計(jì)信息
      System.out.println("字符'" + entry.getKey() + "'出現(xiàn)" + entry.getValue() + "次");
    }
  }

  public static void encryptFile(String srcFile, String destFile, int key) throws IOException {
    String artile = file2String(srcFile);
    //加密文件
    String encryptData = MyEncrypt.encrypt(artile, key);
    //保存加密后的文件
    string2File(encryptData, destFile);
  }

  /**
   * 破解凱撒密碼
   * @param input 數(shù)據(jù)源
   * @return 返回解密后的數(shù)據(jù)
   */
  public static void decryptCaesarCode(String input, String destPath) {
    int deCount = 0;//當(dāng)前解密生成的備選文件數(shù)
    //獲取出現(xiàn)頻率最高的字符信息(出現(xiàn)次數(shù)越多越靠前)
    List<Entry<Character, Integer>> mapList = getMaxCountChar(input);
    for (Entry<Character, Integer> entry : mapList) {
      //限制解密文件備選數(shù)
      if (deCount >= DE_MAX_FILE) {
        break;
      }

      //輸出前幾位的統(tǒng)計(jì)信息
      System.out.println("字符'" + entry.getKey() + "'出現(xiàn)" + entry.getValue() + "次");

      ++deCount;
      //出現(xiàn)次數(shù)最高的字符跟MAGIC_CHAR的偏移量即為秘鑰
      int key = entry.getKey() - MAGIC_CHAR;
      System.out.println("猜測(cè)key = " + key + ", 解密生成第" + deCount + "個(gè)備選文件" + "\n");
      String decrypt = MyEncrypt.decrypt(input, key);

      String fileName = "de_" + deCount + destPath;
      string2File(decrypt, fileName);
    }
  }

  //統(tǒng)計(jì)String里出現(xiàn)最多的字符
  public static List<Entry<Character, Integer>> getMaxCountChar(String data) {
    Map<Character, Integer> map = new HashMap<Character, Integer>();
    char[] array = data.toCharArray();
    for (char c : array) {
      if(!map.containsKey(c)) {
        map.put(c, 1);
      }else{
        Integer count = map.get(c);
        map.put(c, count + 1);
      }
    }

    //輸出統(tǒng)計(jì)信息
    /*for (Entry<Character, Integer> entry : map.entrySet()) {
      System.out.println(entry.getKey() + "出現(xiàn)" + entry.getValue() + "次");
    }*/

    //獲取獲取最大值
    int maxCount = 0;
    for (Entry<Character, Integer> entry : map.entrySet()) {
      //不統(tǒng)計(jì)空格
      if (/*entry.getKey() != ' ' && */entry.getValue() > maxCount) { 
        maxCount = entry.getValue();
      }
    }

    //map轉(zhuǎn)換成list便于排序
    List<Entry<Character, Integer>> mapList = new ArrayList<Map.Entry<Character,Integer>>(map.entrySet());
    //根據(jù)字符出現(xiàn)次數(shù)排序
    Collections.sort(mapList, new Comparator<Entry<Character, Integer>>(){
      @Override
      public int compare(Entry<Character, Integer> o1,
          Entry<Character, Integer> o2) {
        return o2.getValue().compareTo(o1.getValue());
      }
    });
    return mapList;
  }

  public static String file2String(String path) throws IOException {
    FileReader reader = new FileReader(new File(path));
    char[] buffer = new char[1024];
    int len = -1;
    StringBuffer sb = new StringBuffer();
    while ((len = reader.read(buffer)) != -1) {
      sb.append(buffer, 0, len);
    }
    return sb.toString();
  }

  public static void string2File(String data, String path){
    FileWriter writer = null;
    try {
      writer = new FileWriter(new File(path));
      writer.write(data);
    } catch (Exception e) {
      e.printStackTrace();
    }finally {
      if (writer != null) {
        try {
          writer.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }

  }
}

這里寫圖片描述

對(duì)稱加密

介紹

加密和解密都使用同一把秘鑰,這種加密方法稱為對(duì)稱加密,也稱為單密鑰加密。
簡(jiǎn)單理解為:加密解密都是同一把鑰匙。
凱撒密碼就屬于對(duì)稱加密,他的字符偏移量即為秘鑰。

對(duì)稱加密常用算法

AES、DES、3DES、TDEA、Blowfish、RC2、RC4、RC5、IDEA、SKIPJACK 等。

DES:全稱為Data Encryption Standard,即數(shù)據(jù)加密標(biāo)準(zhǔn),是一種使用密鑰加密的塊算法,1976 年被美國(guó)聯(lián)邦政府的國(guó)家標(biāo)準(zhǔn)局確定為聯(lián)邦資料處理標(biāo)準(zhǔn)(FIPS),隨后在國(guó)際上廣泛流傳開來。

3DES:也叫Triple DES,是三重?cái)?shù)據(jù)加密算法(TDEA,Triple Data Encryption Algorithm)塊密碼的通稱。
它相當(dāng)于是對(duì)每個(gè)數(shù)據(jù)塊應(yīng)用三次DES 加密算法。由于計(jì)算機(jī)運(yùn)算能力的增強(qiáng),原版DES 密碼的密鑰長(zhǎng)度變得容易被暴力破解;3DES 即是設(shè)計(jì)用來提供一種相對(duì)簡(jiǎn)單的方法,即通過增加DES 的密鑰長(zhǎng)度來避免類似的攻擊,而不是設(shè)計(jì)一種全新的塊密碼算法。

AES: 高級(jí)加密標(biāo)準(zhǔn)(英語:Advanced Encryption Standard,縮寫:AES),在密碼學(xué)中又稱Rijndael 加密法,是美國(guó)聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn)。這個(gè)標(biāo)準(zhǔn)用來替代原先的DES,已經(jīng)被多方分析且廣為全世界所使用。經(jīng)過五年的甄選流程,高級(jí)加密標(biāo)準(zhǔn)由美國(guó)國(guó)家標(biāo)準(zhǔn)與技術(shù)研究院(NIST)于2001 年11 月26 日發(fā)布于FIPS PUB 197,并在2002 年5 月26 日成為有效的標(biāo)準(zhǔn)。2006 年,高級(jí)加密標(biāo)準(zhǔn)已然成為對(duì)稱密鑰加密中最流行的算法之一。

DES 算法簡(jiǎn)介

DES 加密原理(對(duì)比特位進(jìn)行操作,交換位置,異或等等,無需詳細(xì)了解)

準(zhǔn)備知識(shí)

Bit 是計(jì)算機(jī)最小的傳輸單位。以0 或1 來表示比特位的值
例如數(shù)字3 對(duì)應(yīng)的二進(jìn)制數(shù)據(jù)為:00000011

代碼示例

 int i = 97;
 String bit = Integer.toBinaryString(i);
 //輸出:97 對(duì)應(yīng)的二進(jìn)制數(shù)據(jù)為: 1100001
 System.out.println(i + "對(duì)應(yīng)的二進(jìn)制數(shù)據(jù)為: " + bit);

Byte 與Bit 區(qū)別

數(shù)據(jù)存儲(chǔ)是以“字節(jié)”(Byte)為單位,數(shù)據(jù)傳輸是以大多是以“位”(bit,又名“比特”)為單位,一個(gè)位就代表一個(gè)0 或1(即二進(jìn)制),每8 個(gè)位(bit,簡(jiǎn)寫為b)組成一個(gè)字節(jié)(Byte,簡(jiǎn)寫為B),是最小一級(jí)的信息單位。

Byte 的取值范圍:

//byte 的取值范圍:-128 到127
System.out.println(Byte.MIN_VALUE + "到" + Byte.MAX_VALUE);

即10000000 到01111111 之間,一個(gè)字節(jié)占8 個(gè)比特位

二進(jìn)制轉(zhuǎn)十進(jìn)制圖示:

這里寫圖片描述

任何字符串都可以轉(zhuǎn)換為字節(jié)數(shù)組

String data = "1234abcd";
byte[] bytes = data.getBytes();//內(nèi)容為:49 50 51 52 97 98 99 100

上面數(shù)據(jù)49 50 51 52 97 98 99 100 對(duì)應(yīng)的二進(jìn)制數(shù)據(jù)(即比特位為):

00110001
00110010
00110011
00110100
01100001
01100010
01100011
01100100

將他們間距調(diào)大一點(diǎn),可看做一個(gè)矩陣:

0 0 1 1 0 0 0 1
0 0 1 1 0 0 1 0
0 0 1 1 0 0 1 1
0 0 1 1 0 1 0 0
0 1 1 0 0 0 0 1
0 1 1 0 0 0 1 0
0 1 1 0 0 0 1 1
0 1 1 0 0 1 0 0

之后可對(duì)他們進(jìn)行各種操作,例如交換位置、分割、異或運(yùn)算等,常見的加密方式就是這樣操作比特位的。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論