专栏名称: 安卓开发精选
伯乐在线旗下账号,分享安卓应用相关内容,包括:安卓应用开发、设计和动态等。
目录
相关文章推荐
鸿洋  ·  Android×AI×鸿蒙生态周刊#2|跨端 ... ·  昨天  
开发者全社区  ·  广东售楼小姐“刘佳”火了 ·  2 天前  
开发者全社区  ·  上海某国企裁员10% ·  3 天前  
开发者全社区  ·  私募大瓜PDF ·  3 天前  
51好读  ›  专栏  ›  安卓开发精选

Android 安全加密:对称加密

安卓开发精选  · 公众号  · android  · 2016-09-19 08:36

正文

(点击 上方公众号 ,可快速关注)


来源:GoogleDev

链接:blog.csdn.net/axi295309066/article/details/52491077


对称加密、非对称加密、消息摘要、数字签名等知识都是为了理解数字证书工作原理而作为一个预备知识。数字证书是密码学里的终极武器,是人类几千年历史总结的智慧的结晶,只有在明白了数字证书工作原理后,才能理解Https 协议的安全通讯机制。最终才能在SSL 开发过程中得心应手。


另外,对称加密和消息摘要这两个知识点是可以单独拿来使用的。


数字证书使用到了以上学习的所有知识


  • 对称加密与非对称加密结合使用实现了秘钥交换,之后通信双方使用该秘钥进行对称加密通信。

  • 消息摘要与非对称加密实现了数字签名,根证书机构对目标证书进行签名,在校验的时候,根证书用公钥对其进行校验。若校验成功,则说明该证书是受信任的。

  • Keytool 工具可以创建证书,之后交给根证书机构认证后直接使用自签名证书,还可以输出证书的RFC格式信息等。

  • 数字签名技术实现了身份认证与数据完整性保证。

  • 加密技术保证了数据的保密性,消息摘要算法保证了数据的完整性,对称加密的高效保证了数据处理的可靠性,数字签名技术保证了操作的不可否认性。


通过以上内容的学习,我们要能掌握以下知识点:


  • 基础知识:bit 位、字节、字符、字符编码、进制转换、io

  • 知道怎样在实际开发里怎样使用对称加密解决问题

  • 知道对称加密、非对称加密、消息摘要、数字签名、数字证书是为了解决什么问题而出现的

  • 了解SSL 通讯流程

  • 实际开发里怎样请求Https 的接口




凯撒密码


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 返回加密后的数据

*/

public static 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

return new String ( array );

}

/**

* 解密

* @param input 数据源(被加密后的数据)

* @param key 秘钥,即偏移量

* @return 返回解密后的数据

*/

public static 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

return new String ( array );

}


代码输出结果:



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


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

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


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



5. 破解流程


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

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

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


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



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


/**

* 频率分析法破解凯撒密码

*/

public class FrequencyAnalysis {

//英文里出现次数最多的字符

private static final char MAGIC_CHAR = 'e' ;

//破解生成的最大文件数

private static final int DE_MAX_FILE = 4 ;

public static void main ( 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" );

}

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 ) {

//输出前几位的统计信息

System . out . println ( "字符'" + entry . getKey () + "'出现" + 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 数据源

* @return 返回解密后的数据

*/

public static void decryptCaesarCode ( 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里出现最多的字符

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 );

}

}

//输出统计信息

/*for (Entry 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

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

}

}

}

}

}



对称加密


介绍


加密和解密都使用同一把秘钥,这种加密方法称为对称加密,也称为单密钥加密。 简单理解为:加密解密都是同一把钥匙。


凯撒密码就属于对称加密,他的字符偏移量即为秘钥。


对称加密常用算法


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


DES: 全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1976 年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),随后在国际上广泛流传开来。


3DES: 也叫Triple DES,是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称。

它相当于是对每个数据块应用三次DES 加密算法。由于计算机运算能力的增强,原版DES 密码的密钥长度变得容易被暴力破解;3DES 即是设计用来提供一种相对简单的方法,即通过增加DES 的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法。


AES: 高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael 加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001 年11 月26 日发布于FIPS PUB 197,并在2002 年5 月26 日成为有效的标准。2006 年,高级加密标准已然成为对称密钥加密中最流行的算法之一。


DES 算法简介


DES 加密原理(对比特位进行操作,交换位置,异或等等,无需详细了解)


准备知识


Bit 是计算机最小的传输单位。以0 或1 来表示比特位的值

例如数字3 对应的二进制数据为:00000011


代码示例


int i = 97 ;

String bit = Integer . toBinaryString ( i );

//输出:97 对应的二进制数据为: 1100001

System . out . println ( i + "对应的二进制数据为: "







请到「今天看啥」查看全文