1 Hash函数
Hash函数用于抽取特征
验证黑客是否修改文件,页面是否更新,已经数字签名的签名部分(之后再用非对称加密体系加密)
2 Hash函数需求
给定一个hash 函数 ,不应该能够反向得到一个文件
强的单值hash应该能够应对不同的相关性挑战。
Determinism 确定性
一个文档只有一个hash 值。
Uniform distribution 统一发布
所以hash值看起来很相似
Impossible to reverse engineer 不可反向工程
无法简单产生一个与对应hash code相等的文档。
No collisions 无冲突
俩个文档拥有相同的hash code应该是极难找到的。
Sensitive dependence on initial conditions
文档少量改变导致hash code巨大改变。(雪崩效应)
Randomness 随机性
哈希码将不会透露文档本身的任何信息。
3 摘要算法
SHA-1 SHA-256 SHA-384 SHA-512 MD2 MD5 RipeMD160 Tiger Whirlpool
最常用SHA-1
4 计算信息摘要
分为4步:
1 使用特定的算法作为参数,调用MessageDigest.getInstance()来获得一个MessageDigest对象
2 向 update()方法传递数据
3 如果有更多的数据,再进行2
4 调用digest()方法来生成计算得到的摘要
5 信息摘要的其他访问方法
public final Provider getProvider( )
public final String getAlgorithm( )
public final int getDigestLength( )
6 摘要流
DigestInputStream
DigestOutputStream
对于输入而言
DigestInputStream dis = new DigestInputStream(InputStream,MessageDisgest);
然后dis.read
如果你想查看结果,使用:
MessageDigest md = dis.getMessageDigest();
result = md.disget();
7 Keys
接下来讨论的加密算法,都是基于Key的。
56bits及以下被看做无法保护安全,112bits看做最低保护。但是不仅仅是Key 长度,加密算法本身也觉得了安全性。
8 密钥体系和公钥体系
两种加密形式:对称和非对称的加密
例如AES,对称加密,使用相同的密钥来进行加密和解密
9 密码保存
java.security.KeyStore是一个简单的,好用的保存密码的工作
10 密码类
public class Cipher extends Object
通常构造包括两种形式:
“加密算法”或者
“加密算法/工作模式/填充方式”
例如:
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
构造函数:
public static final Cipher getInstance(String transformation)
throws NoSuchAlgorithmException, NoSuchPaddingException
public static final Cipher getInstance(String transformation, String provider)
throws NoSuchAlgorithmException, NoSuchProviderException,
NoSuchPaddingException
transformation包含了算法,模式,填充方式的一些信息:
例如:"DES", "PBEWithMD5AndDES", and "DES/ECB/PKCS5Padding".
11 JCE标准加密算法集合
Name | Algorithm |
---|---|
AES (a.k.a. Rijndael) | 高级加密算法,128位密文,密钥长度128,192,256 |
DES | 数据加密算法,64位密文,56位密钥 |
DESede | 3重DES ede是加密解密加密的意思 |
PBEWithMD5 AndDES | 基于口令的加密。需要盐值(salt)。 "PKCS #5: Password-Based Encryption Standard," Version 1.5, Nov. 1993; |
PBEWithMD5 AndTripleDES | 基于口令的加密。 |
PBEWithSHA1AndDESede | 基于口令的加密,使用DES加密和SHA1哈希。也需要初始化向量。 |
PBEWithMD5AndTripleDES | 基于口令的加密,使用DES加密和SHA1哈希。也需要盐值和初始化向量。 |
RSA |
这个算法可能是NSA不可渗透的。
|
IDEA | 网络数据加密算法。64位密文和128位密钥。专利已过期 |
RC2 | 可变的64位对称加密。NSA可能能破译这个。 |
ARCFOUR (a.k.a. RC4) | 弱的流式算法。曾用于网景公司的SSL。用于WEP。 |
Blowfish | 无专利的快速的,免费的,对称的,可变密钥长度的(32~448bits)64位密文的用于替代DES加密的一种算法。 |
Twofish | 无专利的快速的,免费的,对称的,可变密钥长度的加密。 |
Skipjack | NSA设计的80位密钥的对称加密算法。实践上面不可攻击。 |
Serpent | 对称密钥长度为128,192,256。128位密文。这是一个高性能的并发设计。 |
12 加密算法模式
Name | Mode |
---|---|
ECB |
电子代码本模式。64位块将独立进行加密,当然它也能独立解密。所以较其他模式要较弱。它不需要初始化向量。 |
CBC | 加密块锁链模式,加密文件的最佳选择,使用初始化向量。 |
CFB | K-bit Cipher反馈模式。流数据的最佳实时加密的选择。需要初始化向量 |
OFB | K-bit Cipher反馈模式。1位的错误将产生1位的密文错误。 |
PCBC | Propagating Cipher Block Chaining, as used in pre-Version 5 Kerberos; similar to the more secure CBC mode used in Kerberos Version 5 and later; uses an initialization vector. |
13 填充策略
Name | Scheme |
---|---|
NoPadding | 不填充任何填充字节 |
ZeroByte | 用0填充,不推荐。 |
PKCS5Padding |
|
PKCS7Padding |
|
WithCTS |
|
SSL3Padding |
|
14 加密步骤
使用Cipher有以下几步:
1 为cipher创建key
2 使用 transformation来获得实例
3 通过传递Cipher.ENCRYPT_MODE和key给init方法来进行初始化
4 使用update来填充数据
5 如果有更多数据,重复4
6 调用doFinal( ).
15 init方法
需要4个东西
-
The mode to operate in (encryption or decryption; not a block cipher mode)
-
A key
-
Algorithm parameters, e.g., an initialization vector
-
A source of randomness
16 加解密模式
加密或者是解密
public static final int ENCRYPT_MODE public static final int DECRYPT_MODE
17 Key
通常先要生成KeySpec
然后利用KeySpec生成Key
18 CipherStream
public class CipherInputStream extends FilterInputStream
CipherInputStream
CipherOutputStream
一个完整的例子:
import java.io.*;
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class DigestDecryptor {
public static void main(String[] args)
throws I OExcedption, GeneralSecurityException {
if (args.length != 3) {
System.err.println("Usage: java DigestDecryptor infile outfile password");
return;
}
String infile = args[0];
String outfile = args[1];
String password = args[2];
if (password.length( ) < 8 ) {
System.err.println("Password must be at least eight characters long");
}
FileInputStream fin = new FileInputStream(infile);
FileOutputStream fout = new FileOutputStream(outfile);
// Get the digest.
FileInputStream digestIn = new FileInputStream(infile + ".digest");
DataInputStream dataIn = new DataInputStream(digestIn);
// SHA digests are always 20 bytes long.
byte[] oldDigest = new byte[20];
dataIn.readFully(oldDigest);
dataIn.close( );
// Create a key.
byte[] desKeyData = password.getBytes( );
DESKeySpec desKeySpec = new DESKeySpec(desKeyData);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey desKey = keyFactory.generateSecret(desKeySpec);
// Use Data Encryption Standard.
Cipher des = Cipher.getInstance("DES/ECB/PKCS5Padding");
des.init(Cipher.DECRYPT_MODE, desKey);
CipherOutputStream cout = new CipherOutputStream(fout, des);
// Use SHA digest algorithm.
MessageDigest sha = MessageDigest.getInstance("SHA");
DigestInputStream din = new DigestInputStream(fin, sha);
byte[] input = new byte[64];
while (true) {
int bytesRead = din.read(input);
if (bytesRead == -1) break;
cout.write(input, 0, bytesRead);
}
byte[] newDigest = sha.digest( );
if (!MessageDigest.isEqual(newDigest, oldDigest)) {
System.out.println("Input file appears to be corrupt!");
}
din.close( );
cout.flush( );
cout.close( );
}
}
这个例子完整的描述了如何使用加密和摘要.
1 从文件中读取字符数组oldDigest (FileInputStream是对FileInputStream的包装)
2 创建DESKeySpec
3 创建SecretKeyFactory(指定DES加密算法)
4 利用SecretKeyFactory和DESKeySpec创建DESKey :
SecretKey desKey = keyFactory.generateSecret(desKeySpec);
5 构造Cipher(指定加密算法,工作模式,填充模式)
6 利用desKey初始化Cipher
7 利用Cipher和潜在输出流来构建CipherOutputStream
8 将读入的数据使用CipherOutputStream写入。