课堂 | Android安全加密:对称加密一、凯撒密码1、概述凯撒密码作为一种最为古老的对称加密体制,在古罗马的时候都已经很流行,他的基本思想是:通过把字母移动一

课堂 | Android安全加密:对称加密


一、凯撒密码


1、概述


凯撒密码作为一种最为古老的对称加密体制,在古罗马的时候都已经很流行,他的基本思想是:通过把字母移动一定的位数来实现加密和解密。明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。例如,当偏移量是3 的时候,所有的字母A 将被替换成D,B 变成E,由此可见,位数就是凯撒密码加密和解密的密钥。


例如:字符串”ABC”的每个字符都右移3 位则变成”DEF”,解密的时候”DEF”的每个字符左移3 位即能还原,如下图所示:




2、准备知识

//字符转换成ASCII 码数值   char charA = 'a';   
 int intA = charA; //char 强转为int 即得到对应的ASCII 码值,’a’的值为97   
//ASCII 码值转成char  
int intA = 97;//97 对应的ASCII 码’a’  
char charA = (char) intA; //int 值强转为char 即得到对应的ASCII 字符,即'a'



3、凯撒密码的简单代码实现

  /**   
     * 加密   
     * @param input 数据源(需要加密的数据)   
     * @param key 秘钥,即偏移量   
     * @return 返回加密后的数据   
     */   
    publicstatic String encrypt(String input, int key){   
        //得到字符串里的每一个字符           char[] array = input.toCharArray();   

        for (int i = 0; i < array.length; ++i) {   
            //字符转换成ASCII 码值               int ascii = array[i];   
            //字符偏移,例如a->b               ascii = ascii + key;   
            //ASCII 码值转换为char               char newChar = (char) ascii;   
            //替换原有字符               array[i] = newChar;   

            //以上4 行代码可以简写为一行               //array[i] = (char) (array[i] + key);           }   

        //字符数组转换成String           returnnewString(array);   
    }   

    /**   
     * 解密   
     * @param input 数据源(被加密后的数据)   
     * @param key 秘钥,即偏移量   
     * @return 返回解密后的数据   
     */   
    publicstatic String decrypt(String input, int key){   
        //得到字符串里的每一个字符           char[] array = input.toCharArray();   
        for (int i = 0; i < array.length; ++i) {   
            //字符转换成ASCII 码值               int ascii = array[i];   
            //恢复字符偏移,例如b->a               ascii = ascii - key;   
            //ASCII 码值转换为char               char newChar = (char) ascii;   
            //替换原有字符               array[i] = newChar;   

            //以上4 行代码可以简写为一行               //array[i] = (char) (array[i] - key);           }   

        //字符数组转换成String           returnnewString(array);   
    }

代码输出结果: 




4、破解凯撒密码:频率分析法


凯撒密码加密强度太低,只需要用频度分析法即可破解。 


在任何一种书面语言中,不同的字母或字母组合出现的频率各不相同。而且,对于以这种语言书写的任意一段文本,都具有大致相同的特征字母分布。比如,在英语中,字母E 出现的频率很高,而X 则出现得较少。


英语文本中典型的字母分布情况如下图所示: 




5、破解流程


  • 统计密文里出现次数最多的字符,例如出现次数最多的字符是是’h’。

  • 计算字符’h’到’e’的偏移量,值为3,则表示原文偏移了3 个位置。

  • 将密文所有字符恢复偏移3 个位置。


注意点:统计密文里出现次数最多的字符时,需多统计几个备选,因为最多的可能是空格或者其他字符,例如下图出现次数最多的字符’#’是空格加密后的字符,’h’才是’e’偏移后的值。 




解密时要多几次尝试,因为不一定出现次数最多的字符就是我们想要的目标字符,如下图,第二次解密的结果才是正确的。

/**   
 * 频率分析法破解凯撒密码   
 */   publicclassFrequencyAnalysis{   
    //英文里出现次数最多的字符       privatestaticfinalchar MAGIC_CHAR = 'e';   
    //破解生成的最大文件数       privatestaticfinalint DE_MAX_FILE = 4;   

    publicstaticvoidmain(String[] args)throws Exception {   
        //测试1,统计字符个数           //printCharCount("article1_en.txt");           //加密文件           //int key = 3;           //encryptFile("article1.txt", "article1_en.txt", key);           //读取加密后的文件           String artile = file2String("article1_en.txt");   
        //解密(会生成多个备选文件)           decryptCaesarCode(artile, "article1_de.txt");   
    }   

    publicstaticvoidprintCharCount(String path)throws IOException{   
        String data = file2String(path);   
        List<Entry<Character, Integer>> mapList = getMaxCountChar(data);   
        for (Entry<Character, Integer> entry : mapList) {   
            //输出前几位的统计信息               System.out.println("字符'" + entry.getKey() + "'出现" + entry.getValue() + "次");   
        }   
    }   

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

    /**   
     * 破解凯撒密码   
     * @param input 数据源   
     * @return 返回解密后的数据   
     */   
    publicstaticvoiddecryptCaesarCode(String input, String destPath){   
        int deCount = 0;//当前解密生成的备选文件数           //获取出现频率最高的字符信息(出现次数越多越靠前)           List<Entry<Character, Integer>> mapList = getMaxCountChar(input);   
        for (Entry<Character, Integer> entry : mapList) {   
            //限制解密文件备选数               if (deCount >= DE_MAX_FILE) {   
                break;   
            }   

            //输出前几位的统计信息               System.out.println("字符'" + entry.getKey() + "'出现" + entry.getValue() + "次");   

            ++deCount;   
            //出现次数最高的字符跟MAGIC_CHAR的偏移量即为秘钥               int key = entry.getKey() - MAGIC_CHAR;   
            System.out.println("猜测key = " + key + ", 解密生成第" + deCount + "个备选文件" + "\n");   
            String decrypt = MyEncrypt.decrypt(input, key);   

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

    //统计String里出现最多的字符       publicstatic 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);   
            }   
        }   

        //输出统计信息           /*for (Entry<Character, Integer> entry : map.entrySet()) {   
            System.out.println(entry.getKey() + "出现" + entry.getValue() +  "次");   
        }*/   

        //获取获取最大值           int maxCount = 0;   
        for (Entry<Character, Integer> entry : map.entrySet()) {   
            //不统计空格               if (/*entry.getKey() != ' ' && */entry.getValue() > maxCount) {    
                maxCount = entry.getValue();   
            }   
        }   

        //map转换成list便于排序           List<Entry<Character, Integer>> mapList = new ArrayList<Map.Entry<Character,Integer>>(map.entrySet());   
        //根据字符出现次数排序           Collections.sort(mapList, new Comparator<Entry<Character, Integer>>(){   
            @Override   
            publicintcompare(Entry<Character, Integer> o1,   
                    Entry<Character, Integer> o2){   
                return o2.getValue().compareTo(o1.getValue());   
            }   
        });   
        return mapList;   
    }   

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

    publicstaticvoidstring2File(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();   
                }   
            }   
        }   

    }   
}



二、对称加密


蓝盾学院订阅号(BDCollegedy)

 查看原文  分享到微信  文章为作者独立观点,不代表大不六文章网立场
蓝盾学院订阅号
BDCollegedy
蓝盾学院专注于信息安全培训、咨询及相关服务,致力于新型领先技术和实践的培训推广,可开展CISP、INSPC、OCP/OCM等十几种认证类及职业鉴定类培训。专职讲师,具备十年以上工作经验,采用全真实战模式,培养高级实用型IT专业人才。

相关

最新更新

本站所有信息来源于互联网,用于学习参考使用,版权归原作者所有!
微信人生 分享最新微信头条新闻