Java加密解密和数字签名完整代码示例
常见的加密算法
基本的单向加密算法:
BASE64严格地说,属于编码格式,而非加密算法
MD5(MessageDigestalgorithm5,信息摘要算法)
SHA(SecureHashAlgorithm,安全散列算法)
HMAC(HashMessageAuthenticationCode,散列消息鉴别码)
复杂的对称加密(DES、PBE)、非对称加密算法:
DES(DataEncryptionStandard,数据加密算法)
PBE(Password-basedencryption,基于密码验证)
RSA(算法的名字以发明者的名字命名:RonRivest,AdiShamir和LeonardAdleman)
DH(Diffie-Hellman算法,密钥一致协议)
DSA(DigitalSignatureAlgorithm,数字签名)
ECC(EllipticCurvesCryptography,椭圆曲线密码编码学)
数字签名
算法简述
数字签名算法可以看做是一种带有密钥的消息摘要算法,并且这种密钥包含了公钥和私钥。也就是说,数字签名算法是非对称加密算法和消息摘要算法的结合体。
特点
数字签名算法要求能够验证数据完整性、认证数据来源,并起到抗否认的作用。
原理
数字签名算法包含签名和验证两项操作,遵循私钥签名,公钥验证的方式。
签名时要使用私钥和待签名数据,验证时则需要公钥、签名值和待签名数据,其核心算法主要是消息摘要算法。
1.消息摘要
StringbeforeDegist="asdf"; System.out.println("摘要前:"+beforeDegist); //初始信息要转换成字节流的形式 byte[]plainText=beforeDegist.getBytes("UTF8"); //使用getInstance("算法")来获得消息摘要,这里使用SHA-1的160位算法或者MD5算法 geDigestmessageDigest=MessageDigest.getInstance("SHA-1"); MessageDigestmessageDigest=MessageDigest.getInstance("MD5"); System.out.println("/n"+messageDigest.getProvider().getInfo()); //开始使用算法 messageDigest.update(plainText); //输出算法运算结果 StringafterDegist=newString(messageDigest.digest(),"UTF8"); System.out.println("摘要后:"+afterDegist);
2.私钥加密
/** *此例子是对一个字符串信息,用一个私钥(key)加密,然后在用该私钥解密,验证是否一致 *私钥加密,是对称加密 *使用对称算法。比如:A用一个密钥对一个文件加密,而B读取这个文件的话,则需要和A一样的密钥,双方共享一 *个私钥(而在web环境下,私钥在传递时容易被侦听) * *附:主要对称算法有:DES(实际密钥只用到56位) *AES(支持三种密钥长度:128、192、256位),通常首先128位,其他的还有DESede等 */Stringbefore="asdf"; byte[]plainText=before.getBytes("UTF8"); //STEP1.
System.out.println("StartgenerateAESkey."); //得到一个使用AES算法的KeyGenerator的实例 KeyGeneratorkeyGen=KeyGenerator.getInstance("AES"); //定义密钥长度128位 keyGen.init(128); //通过KeyGenerator产生一个key(密钥算法刚才已定义,为AES) Keykey=keyGen.generateKey(); System.out.println("FinishgeneratingAESkey="+key);
//STEP2.
//获得一个私钥加密类Cipher,定义Cipher的基本信息:ECB是加密方式,PKCS5Padding是填充方法 Ciphercipher=Cipher.getInstance("AES/ECB/PKCS5Padding"); //System.out.println("/n"+cipher.getProvider().getInfo());
//STEP3.
//使用私钥加密 System.out.println("/n用私钥加密..."); //把刚才生成的key当作参数,初始化使用刚才获得的私钥加密类,Cipher.ENCRYPT_MODE意思是加密 cipher.init(Cipher.ENCRYPT_MODE,key); //私钥加密类Cipher进行加密,加密后返回一个字节流byte[] byte[]cipherText=cipher.doFinal(plainText); //以UTF8格式把字节流转化为String Stringafter1=newString(cipherText,"UTF8"); System.out.println("用私钥加密完成:"+after1);
//STEP4.
[java]viewplaincopy //使用私钥对刚才加密的信息进行解密,看看是否一致,Cipher.DECRYPT_MODE意思是解密钥 System.out.println("/n用私钥解密..."); cipher.init(Cipher.DECRYPT_MODE,key); //对刚才私钥加密的字节流进行解密,解密后返回一个字节流byte[] byte[]newPlainText=cipher.doFinal(cipherText); Stringafter2=newString(newPlainText,"UTF8"); System.out.println("用私钥解密完成:"+after2);
3.公钥加密
Stringbefore="asdf"; byte[]plainText=before.getBytes("UTF8"); //产生一个RSA密钥生成器KeyPairGenerator(顾名思义:一对钥匙生成器) KeyPairGeneratorkeyGen=KeyPairGenerator.getInstance("RSA"); //定义密钥长度1024位 keyGen.initialize(1024); //通过KeyPairGenerator产生密钥,注意:这里的key是一对钥匙!! KeyPairkey=keyGen.generateKeyPair(); //获得一个RSA的Cipher类,使用公钥加密 Ciphercipher=Cipher.getInstance("RSA/ECB/PKCS1Padding"); //System.out.println("/n"+cipher.getProvider().getInfo()); System.out.println("/n用公钥加密..."); //Cipher.ENCRYPT_MODE意思是加密,从一对钥匙中得到公钥key.getPublic() cipher.init(Cipher.ENCRYPT_MODE,key.getPublic()); //用公钥进行加密,返回一个字节流 byte[]cipherText=cipher.doFinal(plainText); //以UTF8格式把字节流转化为String Stringafter1=newString(cipherText,"UTF8"); System.out.println("用公钥加密完成:"+after1); //使用私钥解密 System.out.println("/n用私钥解密..."); //Cipher.DECRYPT_MODE意思是解密模式,从一对钥匙中得到私钥key.getPrivate() cipher.init(Cipher.DECRYPT_MODE,key.getPrivate()); //用私钥进行解密,返回一个字节流 byte[]newPlainText=cipher.doFinal(cipherText); Stringafter2=newString(newPlainText,"UTF8"); System.out.println("用私钥解密完成:"+after2);
4.数字签名
/** *此例子是数字签名的例子,使用RSA私钥对消息摘要(这里指的是原始数据)进行签名,然后使用公钥验证签名 * *A通过使用B的公钥加密数据后发给B,B利用B的私钥解密就得到了需要的数据(进过B公钥加密的数据只有B的私钥能够 *解开,C没有B的私钥,所以C解不开,但C可以使用B的公钥加密一份数据发给B,这样一来,问题来了,B收到的数据到 *底是A发过来的还是C发过来的呢) *由于私钥是唯一的,那么A就可以利用A自己的私钥进行加密,然后B再利用A的公钥来解密,就可以确定:一定是A的消 *息,数字签名的原理就基于此 * *总结:A想将目标数据传给B,此时A需要准备1和2两部分 *1:A使用B的公钥将原始信息加密,以起到保密作用(只有B的私钥能解开,其他人使用其他钥匙都解不开,当然就保密咯) *2:A使用A的私钥将原始信息的摘要进行签名,以起到接收方B确定是A发过来的作用(A用A的私钥对目标数据的摘要进行签 *名,然后传给B,同时,C用C的私钥对任意信息进行签名也传给B,B想接受的是A的数据(比如说一个转帐请求),于是B *就通过A的公钥对接受到的两个信息进行解密,解开的就是A(A的公钥能且只能解开A的私钥加密的数据)) */ Stringbefore="asdf"; byte[]plainText=before.getBytes("UTF8"); //形成RSA公钥对 KeyPairGeneratorkeyGen=KeyPairGenerator.getInstance("RSA"); keyGen.initialize(1024); KeyPairkey=keyGen.generateKeyPair(); //使用私钥签名********************************************************** Signaturesig=Signature.getInstance("SHA1WithRSA"); sig.initSign(key.getPrivate()); //sig对象得到私钥 //签名对象得到原始数据 sig.update(plainText); //sig对象得到原始数据(现实中用的是原始数据的摘要,摘要的是单向的,即摘要算法后无法解密) byte[]signature=sig.sign(); //sig对象用私钥对原始数据进行签名,签名后得到签名signature em.out.println(sig.getProvider().getInfo()); Stringafter1=newString(signature,"UTF8"); System.out.println("/n用私钥签名后:"+after1); //使用公钥验证 sig.initVerify(key.getPublic()); //sig对象得到公钥 //签名对象得到原始信息 sig.update(plainText); //sig对象得到原始数据(现实中是摘要) try{ if(sig.verify(signature)){ //sig对象用公钥解密签名signature得到原始数据(即摘要),一致则true System.out.println("签名验证正确!!"+newString(plainText,"UTF8")); }else{ System.out.println("签名验证失败!!"); } } catch(SignatureExceptione){ System.out.println("签名验证失败!!"); }
5.数字证书
/** *此例是对“数字证书”文件的操作 *java平台(在机器上安装jdk)为你提供了密钥库(证书库),cmd下提供了keytool命令就可以创建证书库 * *在运行此例前: *在c盘目录下创建一个证书,指定证书库为BocsoftKeyLib,创建别名为TestCertification的一条证书,它指定用 *RSA算法生成,且指定密钥长度为1024,证书有效期为1年 *导出证书文件为TC.cer已存于本地磁盘C:/ *密码是qazzaq */ try{ //前提:将证书库中的一条证书导出到证书文件(我写的例子里证书文件叫TC.cer) //从证书文件TC.cer里读取证书信息 CertificateFactorycf=CertificateFactory.getInstance("X.509"); FileInputStreamin=newFileInputStream("C:/TC.cer"); //将文件以文件流的形式读入证书类Certificate中 Certificatec=cf.generateCertificate(in); System.err.println("转换成String后的证书信息:"+c.toString()); */ //或者不用上面代码的方法,直接从证书库中读取证书信息,和上面的结果一摸一样 Stringpass="qazzaq"; FileInputStreamin2=newFileInputStream("C:/BocsoftKeyLib"); KeyStoreks=KeyStore.getInstance("JKS"); ks.load(in2,pass.toCharArray()); Stringalias="TestCertification"; //alias为条目的别名 Certificatec=ks.getCertificate(alias); System.err.println("转换成String后的证书信息:"+c.toString()); //获取获取X509Certificate类型的对象,这是证书类获取Certificate的子类,实现了更多方法 X509Certificatet=(X509Certificate)c; //从信息中提取需要信息 System.out.println("版本号:"+t.getVersion()); System.out.println("序列号:"+t.getSerialNumber().toString(16)); System.out.println("主体名:"+t.getSubjectDN()); System.out.println("签发者:"+t.getIssuerDN()); System.out.println("有效期:"+t.getNotBefore()); System.out.println("签名算法:"+t.getSigAlgName()); byte[]sig=t.getSignature(); //签名值 PublicKeypk=t.getPublicKey(); byte[]pkenc=pk.getEncoded(); System.out.println("公钥:"); for(inti=0;i总结
以上就是本文关于Java加密解密和数字签名完整代码示例的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!