您的位置:首页 > 编程语言 > Java开发

java安全之加密(对称与非对称)

2014-07-03 20:53 543 查看
一些基本的安全知识

l 对称加密与非对称加密

ü 对称加密称为密钥加密,速度快,但加密和解密的钥匙必须相同,只有通信双方才能知道钥匙

ü 非对称加密称为公钥加密,速度慢,加密和解密的钥匙不相同,某一个人持有私钥,任何人都可以知道公钥

问题:想让任何陌生人都可以与你进行加密数据的交换,且加密速度要快,如何实现呢?

l 数字摘要与MD5/SHA算法

ü 作用:数据的完整性校验

l 数字签名

ü 功能:必须能够验证内容没有修改,必须能够验证内容确实是被发送方签署

ü 方案:发送方的公钥可以验证发送方签名的真实性,数字摘要可以验证内容没有修改

l 数字证书

ü 问题:如何确认对方提供的公钥的真实性。

ü 方案:每个人或机构的公钥和私钥由一些权威的机构产生!

非对称加密,好比我研制的毒药,谁都可以购买我的毒药去放毒,但解药只有我自己才有。

md5算法可用于对一段信息进行不可逆的变换运算,产生一个128比特位的数字摘要。如果对输入信息作了任何形式的改变,对改变后的信息再次进行MD5运算所产生的数字摘要,与改变前的内容所运算出的MD5数字摘要都是不同的。MD5不是加密,因为结果是不能恢复出原始数据的。

你给我一个公钥,说是张孝祥的公钥,我怎么能相信你呢?我上你的网站,你说你是中国工商银行,并出示你的公钥,然后就想与我进行机密数据的传送,我能相信吗?这就需要每个人的公钥和私钥由一些权威可以信赖的机构产生!

密钥加密

l 密钥加密也称为对称加密,速度快,但加密和解密的钥匙必须相同,只有通信双方才能知道钥匙。

l 基本步骤:

• 得到keyGenerator的实例对象,并调用其generateKey()方法创建SecretKey对象。

• 得到Cipher的实例对象,并调用其init()方法指定SecretKey对象和指定要进行加密、还是进行解密操作。

• 调用Cipher对象的doFinal()方法完成加密或解密操作。

l 扩展步骤:

• 把密钥保存为密钥文件并传递给对方,用密钥文件对其他文件加密后,再把加密的结果文件传递给对方,让对方用密钥文件解密。

• 单独使用CipherInputStream或CipherOutputStream都可以完成加密和解密操作,关键在于传入的Cipher对象的操作模式。

• 由于加密时所涉及的secretkey不好记忆和交换,可以使用SecretKeyFactory将口令生成SecretKey。

KeyGenerator.getInstance()其参数是一个算法名,看参数的帮助文档的超链接,再找到Standard Names document. 这个超链接所在页面,就知道有哪些算法了。

代码1:

KeyGeneratorkeyGenerator = KeyGenerator.getInstance("DES");

SecretKeykey = keyGenerator.generateKey();

Ciphercipher = Cipher.getInstance("DES");

cipher.init(Cipher.ENCRYPT_MODE,key);

byte[]source = new byte[]{1,2,3,4};

//***cipher.update()实验的结果有问题,这个方法对最终的加密和解密没有任何影响,可能是底层实现类对这个方法采用了空实现***/

byte[]dest = cipher.doFinal(source);

for(inti=0;i<dest.length;i++){

System.out.println(dest[i]+ ",");

}

System.out.println("------------");

cipher.init(Cipher.DECRYPT_MODE,key);

byte[]source2 = cipher.doFinal(dest);

for(inti=0;i<source2.length;i++){

System.out.println(source2[i]+ ",");

}

代码2:如果要做试验,可以先讲解如何将密钥传递给对方,对方如何恢复密钥,然后再让学生用这个密钥解密我的数据

privatestatic void secretDecrypt() throws Exception {

FileInputStreamfisKey = new FileInputStream("key.key");

ObjectInputStreamois = new ObjectInputStream(fisKey);

SecretKeysecretKey = (SecretKey)ois.readObject();

ois.close();

fisKey.close();

Ciphercipher = Cipher.getInstance("AES");

cipher.init(Cipher.DECRYPT_MODE,secretKey);

FileInputStreamfis = new FileInputStream("dest.txt");

CipherInputStreamcis = new CipherInputStream(fis,cipher);

FileOutputStreamfos = new FileOutputStream("src2.txt");

intb = 0;

while((b=cis.read())!=-1){

fos.write(b);

}

fos.close();

cis.close();

fis.close();

}

privatestatic void secretEncrypt() throws Exception {

KeyGeneratorkeyGenerator = KeyGenerator.getInstance("AES");

SecretKeysecretKey = keyGenerator.generateKey();

FileOutputStreamfosKey = new FileOutputStream("key.key");

ObjectOutputStreamobs = new ObjectOutputStream(fosKey);

obs.writeObject(secretKey);

obs.close();

fosKey.close();

Ciphercipher = Cipher.getInstance("AES");

cipher.init(Cipher.ENCRYPT_MODE,secretKey);

FileInputStreamfis = new FileInputStream("src.txt");

CipherInputStreamcis = new CipherInputStream(fis,cipher);

FileOutputStreamfos = new FileOutputStream("dest.txt");

intb = 0;

while((b=cis.read())!=-1){

fos.write(b);

}

fos.close();

cis.close();

fis.close();

}

代码3:基于口令的加密与解密

1.Cipher.getInstance()方法中指定的参数必须与SecretKeyFactory.getInstance()方法中指定的参数相同。

2.在Cipher.init()方法中必须设置PBEParameterSpec参数,且“盐”的长度必须固定为8个字节。

privatestatic void pwdSecretDecrypt() throws Exception {

SecretKeyFactorykeyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");

KeySpeckeySpec = new PBEKeySpec("itcastzxx".toCharArray());

SecretKeysecretKey = keyFactory.generateSecret(keySpec);

PBEParameterSpecparameterSpec = new PBEParameterSpec(new byte[]{1,2,3,4,5,6,7,8},1000);

Ciphercipher = Cipher.getInstance("PBEWithMD5AndDES");

cipher.init(Cipher.DECRYPT_MODE,secretKey,parameterSpec);

FileInputStreamfis = new FileInputStream("dest.txt");

CipherInputStreamcis = new CipherInputStream(fis,cipher);

FileOutputStreamfos = new FileOutputStream("src2.txt");

intb = 0;

while((b=cis.read())!=-1){

fos.write(b);

}

fos.close();

cis.close();

fis.close();

}

privatestatic void pwdSecretEncrypt() throws Exception {

SecretKeyFactorykeyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");

KeySpeckeySpec = new PBEKeySpec("itcastzxx".toCharArray());

SecretKeysecretKey = keyFactory.generateSecret(keySpec);

PBEParameterSpecparameterSpec = new PBEParameterSpec(new byte[]{1,2,3,4,5,6,7,8},1000);

Ciphercipher = Cipher.getInstance("PBEWithMD5AndDES");

cipher.init(Cipher.ENCRYPT_MODE,secretKey,parameterSpec);

FileInputStreamfis = new FileInputStream("src.txt");

CipherInputStreamcis = new CipherInputStream(fis,cipher);

FileOutputStreamfos = new FileOutputStream("dest.txt");

intb = 0;

while((b=cis.read())!=-1){

fos.write(b);

}

fos.close();

cis.close();

fis.close();

}

公钥加密

l 公钥加密也称为非对称加密、速度慢、加密和解密的钥匙不相同,某一个人持有私钥,任何人都可以知道公钥。

l 基本步骤:

• 得到keyPairGenerator的实例对象,并调用其generateKeyPair()方法创建KeyPair对象。

• 调用KeyPair对象的getPrivate和getPublic方法,分别得到PrivateKey对象和PublicKey对象。

• 得到Cipher的实例对象,并调用其init()方法指定PrivateKey对象或PublicKey对象,并指定要进行加密、还是进行解密操作。

• 调用Cipher对象的doFinal()方法完成加密或解密操作。

l 扩展步骤:

• 把公钥和私钥分别保存为公钥文件和私钥文件,把公钥文件传递给对方,对方用公钥文件对其他文件加密后,再把加密的结果文件传递回来,这边再用私钥文件解密。

• 单独使用CipherInputStream或CipherOutputStream都可以完成加密和解密操作,关键在于传入的Cipher对象的操作模式。

为什么要有公钥加密呢?假如我想与一万个人加密对话,如果用密钥方式,我要制造出一万对密钥,否则,如果只有一对密钥来与这一万个对话,在这一万个人彼此之间就没有机密性可言了。

代码1:

KeyPairGeneratorkeyGenerator = KeyPairGenerator.getInstance("RSA");

KeyPairkeyPair = keyGenerator.generateKeyPair();

PrivateKeyprivateKey = keyPair.getPrivate();

PublicKeypublicKey = keyPair.getPublic();

Ciphercipher = Cipher.getInstance("RSA");

cipher.init(Cipher.ENCRYPT_MODE,publicKey);

byte[] source = new byte[]{1,2,3,4};

byte[]dest = cipher.doFinal(source);

for(inti=0;i<dest.length;i++){

System.out.println(dest[i]+ ",");

}

System.out.println("------------");

cipher.init(Cipher.DECRYPT_MODE,privateKey);

byte[]source2 = cipher.doFinal(dest);

for(inti=0;i<source2.length;i++){

System.out.println(source2[i]+ ",");

}

在这里可以顺带演示一下:“代码改成私钥加密,用公钥解密”。

代码2:

//公钥加密

privatestatic void publicEncrypt() throws Exception{

{

KeyPairGeneratorkeyGenerator = KeyPairGenerator.getInstance("RSA");

KeyPairkeyPair = keyGenerator.generateKeyPair();

PrivateKeyprivateKey = keyPair.getPrivate();

PublicKeypublicKey = keyPair.getPublic();

FileOutputStreamfosPrivateKey = new FileOutputStream("private.key");

FileOutputStreamfosPublicKey = new FileOutputStream("public.key");

ObjectOutputStreamoosPrivateKey = new ObjectOutputStream(fosPrivateKey);

ObjectOutputStreamoosPublicKey = new ObjectOutputStream(fosPublicKey);

oosPrivateKey.writeObject(privateKey);

oosPublicKey.writeObject(publicKey);

oosPrivateKey.close();

oosPublicKey.close();

fosPrivateKey.close();

fosPublicKey.close();

}

FileInputStreamfisPublicKey = new FileInputStream("public.key");

ObjectInputStreamoisPublicKey = new ObjectInputStream(fisPublicKey);

PublicKeypublicKey = (PublicKey)oisPublicKey.readObject();

oisPublicKey.close();

fisPublicKey.close();

Ciphercipher = Cipher.getInstance("RSA");

cipher.init(Cipher.ENCRYPT_MODE,publicKey);

FileInputStreamfis = new FileInputStream("src.txt");

FileOutputStreamfos = new FileOutputStream("dest.txt");

CipherOutputStreamcos = new CipherOutputStream(fos,cipher);

intlen = 0;

bytebuf[] = new byte[1024];

while((len=fis.read(buf))!= -1){

cos.write(buf,0,len);

}

cos.close();

fos.close();

fis.close();

}

//私钥解密

privatestatic void privateDecrypt() throws Exception{

FileInputStreamfisPrivateKey = new FileInputStream("private.key");

ObjectInputStreamoisPrivateKey = new ObjectInputStream(fisPrivateKey);

PrivateKeyprivateKey = (PrivateKey)oisPrivateKey.readObject();

oisPrivateKey.close();

fisPrivateKey.close();

Ciphercipher = Cipher.getInstance("RSA");

cipher.init(Cipher.DECRYPT_MODE,privateKey);

FileInputStreamfis = new FileInputStream("dest.txt");

FileOutputStreamfos = new FileOutputStream("src2.txt");

CipherOutputStreamcos = new CipherOutputStream(fos,cipher);

intlen = 0;

bytebuf[] = new byte[1024];

while((len=fis.read(buf))!= -1){

cos.write(buf,0,len);

}

cos.close();

fos.close();

fis.close();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: