20155212 2016-2017-2 《Java程序设计》第10周学习总结
教材学习内容总结
密码学基础
-
ava API支持多种加密算法。如MessageDigest类,可以构建MD5、SHA等摘要算法;Mac类可以构建HMAC算法;Cipher类可以构建多种加密算法,如DES、AES、Blowfish对称加密算法,以及RSA、DSA、DH等多种非对称加密算法;Signature类可以用于数字签名和签名验证;Certificate类可用于操作证书。
-
安全的三个属性:
- 机密性
- 完整性
- 可用性
-
其他安全技术目标
- 可靠性
- 抗否认性(抗抵赖性)
- 可控性
- 可审查性
- 认证(鉴别)
- 访问控制
-
密码学
- 密码编码学
- 密码分析学
-
密码学常用术语
- 明文
- 密文
- 发送者
- 接受者
- 加密
- 加密算法
- 加密密钥
- 解密
- 解密算法
- 解密密钥
- 密码分析: 指截获密文者试图通过分析截获的密文从而推断出原来的明文或密钥的过程。
- 密码分析者
- 被动攻击
- 主动攻击
- 密码体制:由明文空间、 密文空间、 密钥空间、 加密算法和解密算法五部分构成。
- 密码协议: 有时又称安全协议,是指以密码学为基础的消息交换的通信协议,其目的是在网络环境中提供各种安全服务。
- 密码系统: 指用于加密和解密的系统。 一个密码系统由信源、 加密变换、 解密变换、 信宿和攻击者组成。 密码系统强调密码方案的实际应用,通常应当是一个包含软、硬件的系统。
- 柯克霍夫原则:在19世纪提出的密码理论,即数据的安全基于密钥而不是算法的保密。换句话说, 系统的安全性取决于密钥,对密钥保密,对算法公开。信息论始祖克劳德·艾尔伍德·香农将其改为“ 敌人了解系统”,这样的说法称为香农箴言。柯克霍夫原则是现代密码学设计的基本原则。
- 即使非数学上不可破解,系统也应在实质(实用)程度上无法破解系统内不应含任何机密物, 即使落入敌人手中也不会造成困扰。
- 密钥必须易于沟通和记忆, 而无须写下, 且双方可以很容易地改变密匙。
- 系统应可以用于电讯。
- 系统应可以携带, 不应需要两个人或两个人以上才能使用( 应只要一个人就能使用) 。
- 系统应容易使用, 不致让使用者的脑力过分操劳, 也无须记得长串的规则。
-
密码学家的工具箱:
- 对称密码
- 公钥密码
- 单向散列函数
- 消息认证码
- 数字签名
- 伪随机数生成器
-
根据密钥的使用方法,可以将密码分为对称密码(同一密码)和公钥密码(不同密码)两种。
-
混合密码系统
-
加密
-
解密
-
-
口令(PBE算法)
-
密码与信息安全常识
- 不要使用保密的密码算法
- 使用低强度的密码比不进行任何加密更危险
- 任何密码总有一天都会被破解
- 密码只是信息安全的一部分
Java与密码学
- Java安全体系结构
- JCA(Java CryptographyArchitecture,Java加密体系结构):JCA提供基本的加密框架,如证书、数字签名、消息摘要和密钥对产生器。
- JCE( Java CryptographyExtension,Java加密扩展包):JCE在JCA的基础上作了扩展,提供了各种加密算法、消息摘算法和密钥管理等功能。JCE的实现主要在javax.crypto包(及其子包)中。
- JSSE(Java Secure Sockets Extension,Java安全套接字扩展包):JSSE提供了基于SSL(Secure Sockets Layer,安全套接字层)的加密功能。在网络的传输过程中,信息会经过多个主机(很有可能其中一台就被窃听),最终传送给接收者,这是不安全的。这种确保网络通信安全的服务就由JSSE来提供的。
- JAAS( Java Authentication and Authentication Service, Java鉴别与安全服务):JAAS提供了在Java平台上进行用户身份鉴别的功能。
体验加解密---凯撒密码
- 加密过程:c = m + k (mod n)
- 解密过程:m = c + k (mod n)
/**
* Created by radish608 on 17-4-30.
*/
public class Caesar {
public static void main(String args[]) throws Exception{
String s=args[0];
int key=Integer.parseInt(args[1]);
String es="";
for(int i=0;i<s.length( );i++)
{ char c=s.charAt(i);
if(c>='a' && c<='z') // 是小写字母
{ c+=key%26; //移动key%26位
if(c<'a') c+=26; //向左超界
if(c>'z') c-=26; //向右超界
}
else if(c>='A' && c<='Z') // 是大写字母
{ c+=key%26;
if(c<'A') c+=26;
if(c>'Z') c-=26;
}
es+=c;
}
System.out.println(es);
}
}
Java对称加密-DES
- 对称密钥的生成和保存
- 将密钥通过对象序列化方式保存在文件中,在文件中保存的是对象
- 获取密钥生成器
KeyGenerator kg=KeyGenerator.getInstance("DESede");
- 初始化密钥生成器
kg.init(168);
- 生成密钥
SecretKey k=kg.generateKey( );
- 通过对象序列化方式将密钥保存在文件中
FileOutputStream f=new FileOutputStream("key1.dat"); ObjectOutputStream b=new ObjectOutputStream(f); b.writeObject(k);
- 获取密钥生成器
- 将密钥以字节保存在文件中
- 获取密钥
FileInputStream f=new FileInputStream("key1.dat");
ObjectInputStream b=new ObjectInputStream(f);
Key k=(Key)b.readObject( );
- 获取主要编码格式 ```byte[ ] kb=k.getEncoded( );```。
- 保存密钥编码格式
FileOutputStream f2=new FileOutputStream("keykb1.dat");
f2.write(kb);
- 生成的文件是一个二进制文件,存放的是任意二进制数。
- 每次运行时生成的密钥都不会相同,这就保证了密钥的唯一性。作为对称密钥,只要保证若加密某段文字用的是某个密钥,则解密这段密文时用同样的密钥即可。
- 加密
- 从文件中获取密钥
FileInputStream f=new FileInputStream("key1.dat");
ObjectInputStream b=new ObjectInputStream(f);
Key k=(Key)b.readObject( );
- 创建密码器(Cipher对象)
Cipher cp=Cipher.getInstance("DESede");
- 初始化密码器
cp.init(Cipher.ENCRYPT_MODE, k);
- 获取等待加密的明文
String s="Hello World!";
byte ptext[]=s.getBytes("UTF8");
- 执行加密
byte ctext[]=cp.doFinal(ptext);
- 处理加密结果
FileOutputStream f2=new FileOutputStream("SEnc.dat");
f2.write(ctext);
- 解密
- 获取密文
FileInputStream f=new FileInputStream("SEnc.dat");
int num=f.available();
byte[ ] ctext=new byte[num];
f.read(ctext);
- 获取密钥
FileInputStream f2=new FileInputStream("keykb1.dat");
int num2=f2.available();
byte[ ] keykb=new byte[num2];
f2.read(keykb);
SecretKeySpec k=new SecretKeySpec(keykb,"DESede");
- 创建密码器(Cipher对象)
Cipher cp=Cipher.getInstance("DESede");
- 初始化密码器
cp.init(Cipher.DECRYPT_MODE, k);
- 执行解密
import java.io.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class SDec{
public static void main(String args[]) throws Exception{
// 获取密文
FileInputStream f=new FileInputStream("SEnc.dat");
int num=f.available();
byte[ ] ctext=new byte[num];
f.read(ctext);
// 获取密钥
FileInputStream f2=new FileInputStream("keykb1.dat");
int num2=f2.available();
byte[ ] keykb=new byte[num2];
f2.read(keykb);
SecretKeySpec k=new SecretKeySpec(keykb,"DESede");
// 解密
Cipher cp=Cipher.getInstance("DESede");
cp.init(Cipher.DECRYPT_MODE, k);
byte []ptext=cp.doFinal(ctext);
// 显示明文
String p=new String(ptext,"UTF8");
System.out.println(p);
}
}
Java非对称加密-RSA算法
- 创建RSA公钥和私钥
Java的KeyPairGenerator类提供了一些方法来创建密钥对以便用于非对称加密,密钥对创建好后封装在KeyPair类型的对象中,在KeyPair类中提供了获取公钥和私钥的方法。具体步骤如下:
- 创建密钥对生成器
KeyPairGenerator kpg=KeyPairGenerator.getInstance("RSA");
- 初始化密钥生成器
kpg.initialize(1024);
- 生成密钥对
KeyPair kp=kpg.genKeyPair( );
- 获取公钥和私钥
PublicKey pbkey=kp.getPublic( );
PrivateKey prkey=kp.getPrivate( );
- 加密
- 获取公钥
FileInputStream f=new FileInputStream("Skey_RSA_pub.dat");
ObjectInputStream b=new ObjectInputStream(f);
RSAPublicKey pbk=(RSAPublicKey)b.readObject( );
- 获取公钥的参数(e, n)
BigInteger e=pbk.getPublicExponent();
BigInteger n=pbk.getModulus();
- 获取明文整数(m)
String s="Hello World!";
byte ptext[]=s.getBytes("UTF8");
BigInteger m=new BigInteger(ptext);
- 执行计算
BigInteger c=m.modPow(e,n);
- 解密
- 读取密文
BufferedReader in=
new BufferedReader(new InputStreamReader(
new FileInputStream("Enc_RSA.dat")));
String ctext=in.readLine();
BigInteger c=new BigInteger(ctext);
- 获取私钥
FileInputStream f=new FileInputStream("Skey_RSA_priv.dat");
ObjectInputStream b=new ObjectInputStream(f);
RSAPrivateKey prk=(RSAPrivateKey)b.readObject( );
- 获取私钥的参数(d, n)
BigInteger d=prk.getPrivateExponent( );
BigInteger n=prk.getModulus( );
- 执行计算
BigInteger m=c.modPow(d,n);
- 计算明文整形数对应的字符串
byte[] mt=m.toByteArray();
for(int i=0;i<mt.length;i++){
System.out.print((char) mt[i]);
}
使用密钥协定创建共享密钥
- 密钥分发
- 一般情况下,主要数据通过对称密钥加密,而使用非对称加密来分发对称密钥
- 使用密钥协定来交换对称密钥——DH算法
- 创建DH公钥和私钥
- 和上面使用KeyPairGenerator类创建RSA公钥和私钥类似,只是其参数中指定“DH”,此外在初始化时需要为DH指定特定的参数。
- 创建共享私钥
- 读取自己的DH私钥和对方的DH公钥
FileInputStream f1=new FileInputStream(args[0]);
ObjectInputStream b1=new ObjectInputStream(f1);
PublicKey pbk=(PublicKey)b1.readObject( );
FileInputStream f2=new FileInputStream(args[1]);
ObjectInputStream b2=new ObjectInputStream(f2);
PrivateKey prk=(PrivateKey)b2.readObject( );
- 创建密钥协定对象
KeyAgreement ka=KeyAgreement.getInstance("DH");
- 初始化密钥协定对象
ka.init(prk);
- 执行密钥协定
ka.doPhase(pbk,true);
- 生成共享消息
byte[ ] sb=ka.generateSecret();
Java摘要算法- MD5
java.security包中的MessageDigest类提供了计算消息摘要的方法。
- 生成MessageDigest对象
MessageDigest m=MessageDigest.getInstance("MD5");
- 传入需要计算的字符串
m.update(x.getBytes("UTF8" ));
- 计算信息摘要
byte s[ ]=m.digest( );
- 处理计算结果
String result="";
for (int i=0; i<s.length; i++){
result+=Integer.toHexString((0x000000ff & s[i]) | 0xffffff00).substring(6);
}
教材学习中的问题和解决过程
代码调试中的问题和解决过程
代码托管
上周考试错题总结
结对及互评
点评过的同学博客和代码
其他
- 《Java密码学算法》对于我们而言非常重要,也非常有用。目前我们的密码学学习偏重理论,实践很少。而且,使用C语言编写密码学算法过于麻烦。Java密码学算法的仅仅学习这一周是远远不够的。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 18/18 | 1/1 | 10/10 | |
第二周 | 172/190 | 1/2 | 18/38 | |
第三周 | 464/654 | 1/3 | 23/61 | |
第四周 | 876/1530 | 1/4 | 28/89 | |
第五周 | 831/2361 | 1/5 | 15/114 | |
第六周 | 1404/2765 | 1/6 | 24/138 | |
第七周 | 854/3619 | 2/8 | 15/153 | |
第八周 | 542/4161 | 1/9 | 24/177 | |
第八周 | 1030/5191 | 1/10 | 20/197 | |
第九周 | 479/5670 | 2/12 | 20/217 |
尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。
-
计划学习时间:20小时
-
实际学习时间:20小时
-
改进情况:这周的学习我觉得非常有用,我也很愿意学,而且我觉得这节内容对我们后面的学习乃至以后的工作都可能有很大的帮助。
(有空多看看现代软件工程 课件
软件工程师能力自我评价表)