P9安装root包 提示MD5无法root华为升级包文件校验失败,如何处理

Show Threads
Show Posts
11I have managed SuperSU 2.82 for EMUI 5 right now Hello all &Tecalote OP5OP Uptated - Current Status: Stable Good morning :)
Changelog: &Tecalote OP4Chainfire will add support for Huawei Devices to official SuperSU Official &Tecalote OP3 (quote)
Ask on the
corresponding
forums/threads for stock &zgfg3 (quote)
You are on Stock
b386 yet, right?
have &Tecalote OP
XDA Features
Top Forum Discussions
[ROOT][Android 7.0][EMUI 5.0]SuperSU 2.82 for EMUI 5
SuperSU 2.82 for EMUI 5
Note: SuperSU 2.82 working on EMUI 5 but may not on EMUI 5.0.1 or 5.1
Here is updated SuperSU-2.82-SR5 for EMUI5.0.1
This will work (tested) on EVA (Huawei P9) - based on original SuperSU SR5 by @
Older Versions here: (Thread will get general update soon)
SuperSU-2.82-EMUI5
Changelog: First 4 Versions based on original Chaifires SuperSU 2.82 code with mounting vendor and search for boot_a. These versions are without additional modification by phh superuser files/scripts
The second 3 Versions (a/b)
- 09.06.- are mixed with phh superuser and original Chaifires SuperSU Code (same as 2.79 for EMUI): Download-Links below - for Firmwares before b38x and without loop support
Current Status:
NOTE: If your device has no Root - just flash it with the related TWRP for your device! - But if your device is rooted with previous Versions of SuperSU for EMUI, dont flash it over existing Root but make the steps written below &How do Root&
4 Versions based on original Chainfire SuperSU 2.82 code - 07.06.2017
Succesful tested on P9 b383, b386 and Mate 9, also working on Honor 6x BLN-B360 - but may work also on other devices from Firmwares b38x up and new Nougat Firmwares for Devices, which had Marshmallow until short time ago.
It will probably not work on other Firmwares before b38x (for these devices are the modified versions with mixed code from SuperSU and phh Superuser)
SuperSU-v2.82-EMUI5-SELEnforcing.zip
Just added init.d script, but let's SELinux as it is.
MD5: 1a3ad006760cf
2) SuperSU-v2.82-EMUI5-SELPermissive.zip
Added init.d script and set SELinux permanently to permissive (required for Viper4Android)
MD5: 57a081ba3ba03691c4ffaf9ab141a44e
3) SuperSU-v2.82-EMUI5-KangV-Roms.zip
Added init.d script, SELinux Permissive, Script for K-Settings
MD5: 5e68f7bda04f5
4) SuperSU-v2.82-without-additive.zip - try out, if none of the three above works (its without additional features, just Root)
MD5: bfa6fdeb7ef31a
3 Versions (a/b) mixed with original Chainfire SuperSU 2.82 code and pph superuser code - 09.06.2017
For devices which has no Loop Support yet, but working also on devices, which can succesful use Version 1, 2, 3 and 4.
Kirin 960 based Devices must use Version 6 a/b and 7
Following versions are not compatible with AOSPA based Roms.
5. Version comes in 2 editions (5a and 5b) - should work with devices which have fully working TWRPs - like P9
Version 5/a
- Name: SuperSUv2.82-EMUI5-dm-verity-Enforcing.zip
DOWNLOAD UPDATED VERSION:
0da8bcbf0eb164cb45eb
About:dm-verity and dm-crypt enabled
init.d Support
SELinux Enforcing
Version 5/b - Name: SuperSUv2.82-EMUI5-dm-verity-Permissive.zip
DOWNLOAD UPDATED VERSION:
MD5: 14a0ac7fd3a725ee326ee
About:dm-verity and dm-crypt enabled
init.d Support
permanent SELinux Permissive
Version 5 (a/b) is working (tested) on:Huawei P9
Huawei P9 Lite
Huawei Mate 8
Huawei Mate 9
Not working:Huawei Honor 8 FRD-L09C432B380
Huawei P10 and P10 plus - must have noverity version
6. Version comes in 2 editions - for Kirin 960 based Devices like P10 and P10+
and should work with
other devices which have NOT properly working TWRPs
Version 6/a - Name: SuperSUv2.82-EMUI5-noverity-Enforcing.zip
DOWNLOAD UPDATED VERSION:
MD5: a9f78bbd4b2
About: dm-verity DISABLED
init.d Support
SELinux Enforcing
Version 6/b - Name: SuperSUv2.82-EMUI5-noverity-Permissive.zip
DOWNLOAD UPDATED VERSION:
MD5: 99f06e5fe34bfc119d15e59
About: dm-verity DISABLED
init.d Support
permanent SELinux Permissive
Version 6 (a/b) is working (tested) on:Huawei P10+
Huawei P10
Huawei Mate 9
Huawei P8 Lite 2017
Huawei Honor 8 FRD-L09C432B386
7. Version comes in 2 editions - special for KangV-ROMs on Kirin 960 based Devices.
Version 7/a
- Name: SuperSUv2.82-EMUI5-dm-verity-KangV.zip
DOWNLOAD UPDATED VERSION:
MD5: 8ca92c52a338fd82e923da
Version 7/b - Name: SuperSUv2.82-EMUI5-noverity-KangV.zip
Download for testing issues:
MD5:0df87e5c4a5d41a0ed8be8
About:Version 7/a = dm-verity and dm-crypt enabled
Version 7/b = dm-verity disabled
init.d Support
script for K-Settings
script for busybox in /system/xbin
permanent SELinux Permissive
Version 7/a is working (tested) on:KangV Roms
Huawei Mate 8
Version 7/b is not tested yet!
PREVIOUS FINAL VERSION 2.81 - mixed code with chainfires and phh superusers - was working on most Huawei Devices:
How Do Root:
A) You need unlocked Bootloader and the TWRP related for your device installed!
TWRP for Huawei P9 Nougat you can find here - with Decryption Support by Recognized Developer OldDroid:
B) Look into your settings: Developer options must be enabled and inside: ADB Debugging and USB Debugging, as well as in settings/advanced settings/security &Allow unknown sources& PC should have the driver installed for connecting Phone in Fastboot Mode.
C) Make a TWRP Backup of - boot.img - data - system -vendor - before flashing SuperSUfor EMUI 5 - if one version dont work on your Huawei Device as it should, restore original boot.img with TWRP and try one of the other versions.
Note: If your Phone is not rooted -just flash SuperSU 2.81 EMUI 5 and reboot
- Phone boots up two times and with the second boot you come back to your homescreen with Root.
If your Phone is rooted und you want update SuperSU - dont flash over existing Root, do following steps:
1) Copy SuperSU-2.82.zip to your external SD
2) Make a Complete Unroot from SuperSU App!
3) SuperSU ask: &Should SuperSU restore original boot.img& - check YES (2 times)
4) Phone reboots - dont wait but in the moment your screen is black press VOL+ Button and hold it the whole time until you are booted to TWRP.
5) In TWRP go to install and select SuperSU 2.82, swype to install
6) Search on Homescreen for SuperSU App and open it - look if you're done - if yes =good
NEXT STEPS ONLY IF ROOTING WAS NOT SUCCESFUL OR IF SUPERSU APK CANNOT UNROOT OR RESTORE BOOT.IMG:
Flash original (unmodified) boot.img with Fastboot - or restore boot.img from the Stock TWRP Backup (boot) of same Firmware
- if restored from TWRP Backup, dont restart system, go back and - flash SuperSU
- if flashed instead with Fastboot - disconnect USB from Device and with Power and VOL+ boot to TWRP and flash SuperSU
Note 2: If you are own the SuperSU PRO Version - you have just to update the SuperSU-Pro.apk directly from SuperSU &Upgrade to Pro Version&. You will redirected to Playstore, install the Update!
If your Phone has a Custom Rom like Nougat KangV Rom - you can try to flash over existing Root - if it dont work (its different: for most will work, for some not) you can do:
Unroot with following steps:
0) KangV Roms for Nougat come with prerooted boot.img. SuperSU 2.82 should be able to patch and update it - just try.
If the update fails it would be good to find (or have) the original unmodified boot.img for the Firmware on which Rom is based and restore this.
1) Look into your settings: Developer options must be enabled and inside: ADB Debugging and USB Debugging, as well as in settings/advanced settings/security &Allow unknown sources& PC should have the driver installed for connecting Phone in Fastboot Mode.
2) Copy SuperSU 2.82 EMUI 5
to your external SD
3) Open old or not properly working SuperSU and make a &complete Unroot& - when SuperSU ask you 2 times &Do you want to restore original boot.img& check: YES
Maybe it is successful - perhaps not - if yes:
4) Phone reboots - but it cannot reboot to system!!
5) Instead booting to system you come into Huawei eRecovery - just make SHUTDOWN.
Now same steps, if the restore of original boot.img was not succesful - you must restore original (unmodifiied) boot.img from Firmware. If you have a TWRP-Backup from unrooted original boot.img restore it and go to 8) - if you have not a TWRP Backup for restore - go to step 6)
6) Connect Phone with USB to PC and with Vol- and Power start Phone into fastboot mode.
7) Flash unmodified boot.img with Minimal ADB and Fastboot. Disconnect phone from USB.
8) Press VOL+ with the finger of your left hand and press it all the time and with the finger of your right hand press Power Button.
9) Phone boot up and soon as Huawei Logo is shown on screen, release the Power Button but stay pressing VOL+ the whole time until you are in TWRP.
10) Flash SuperSU 2.82 EMUI 5
11) Phone boots up now two times and will finally boot to system.
12) search for SuperSU on Homescreen - its not on your usual place, its somwhere else on homescreen - open it and you should have now clean SuperSU 2.82
Do this steps just, if you had problems with flashing 2.82
Please report if you rooted your device successful / not succesful - and give information about your Device-model, Build number, TWRP-Version (fully or not properly working, ist it able to mount data with f2fs, make backup and restore?...)
@ - SuperSU Release
@ - phh's SuperUser/ OpenSource SELinux-capable SuperUser
@ - TWRP for P9 Android 7 with Decryption Support
@ - Mate 9 Development
@ - Honor 8 Development
Thanks for the great job.
how do you root it if it's still not rooted? I lost root when I upgraded to nougat and never found out how to get it back
My Devices:
Thanks for job, but 2.81 version is really works? Because the 2.79 is not fully good: there was 1 problem: doesn't delete system
programs with the Titanium Backup.
My Devices: ,
Originally Posted by kazshizka
how do you root it if it's still not rooted? I lost root when I upgraded to nougat and never found out how to get it back
You just need the right TWRP and then flash SuperSU zip, reboot phone without wipe of Dalvik /Cache
Which phone model to you have?
My Devices: ,
Originally Posted by Shyciii
Thanks for job, but 2.81 version is really works? Because the 2.79 is not fully good: there was 1 problem: doesn't delete system
programs with the Titanium Backup.
You need also a good busybox 1.26.2 - I always use the one from YashdSaraf (xda)
My Devices:
Originally Posted by Tecalote
You need also a good busybox 1.26.2 - I always use the one from YashdSaraf (xda)
SuperSU must works without busybox. My friend modified the SuperSU version 2.79, and it works fully.
Originally Posted by Tecalote
You just need the right TWRP and then flash SuperSU zip, reboot phone without wipe of Dalvik /Cache
Which phone model to you have?
My phone is a P9, Model is EVA L-19.
So i need to flash TWRP first? I just used a one click program the last time I rooted it so I'm too sure how to do stuff
My Devices: ,
Originally Posted by kazshizka
My phone is a P9, Model is EVA L-19.
So i need to flash TWRP first? I just used a one click program the last time I rooted it so I'm too sure how to do stuff
You need this TWRP:
And after flash with this TWRP this SuperSU and you are rooted
If you don't know how to flash TWRP, search related Thread
Originally Posted by Tecalote
You need this TWRP:
And after flash with this TWRP this SuperSU and you are rooted
If you don't know how to flash TWRP, search related Thread
Many Thanks!!!!
My Devices: ,
Originally Posted by Shyciii
SuperSU must works without busybox. My friend modified the SuperSU version 2.79, and it works fully.
This SuperSU works fully - but we talked about TitaniumBackup and this would may work better with Busybox.
Root without Busybox is like a tree without leaves.
I have not tested yet, if SuperSU works in case of TitaniumBackup without Busybox.
But you can test it by yourself.
And if your friend make it better let him do this Job - but don't discuss with me about Busybox
Guest Quick Reply (no urls or BBcode)
-- XDA Classic
-- XDA 2010
-- XDA 2013
---- XDA 2013 Beta - 1024
-- XDA 2015
---- 2015 - Dark Theme
');}else if(xda_ad_choice=="sortable"){document.write('\x3Cscript src="//tags-cdn.deployads.com/a/xda-developers.com.js" async >\x3C/script>');document.write('');(deployads=window.deployads||[]).push({});}}
We're Social平板/笔记本
HiLink生态产品
终端云服务专区
引用别人的荣耀6P刷机&Root教程,并讲下自己经验
&渐入佳境&
来自:浏览器
【【HRT_ycjeson】Plus 解锁教程、解锁之后即可刷机&root】
http://cn.club.vmall.com/forum.php?mod=viewthread&tid=2558280
更多精彩请点击下载最新客户端:http://a.vmall.com/appdl/C?cno=4030001&source=CN
【【更新】◆◆◆全国首发荣耀6PLUS ROOT详细教程!◆◆◆】
http://cn.club.vmall.com/forum.php?mod=viewthread&tid=2257413
更多精彩请点击下载最新花粉俱乐部客户端:http://a.vmall.com/appdl/C?cno=4030001&source=EMUICN
我是按这两个教程解锁与Root,
1、解锁时得注意,若是Win7必须先取得管理员权限,具驱动得确保安装好。
2、Root时,用英文的rec兼容好点。
3、Superuser Root包,得放机身的内存中,别放SD卡上,因为不知明原因,教程的三方rec是无法挂载或检测exfat的SD卡,fat32的卡我没测试过。
4、建议Root时用荣耀6p低版本的系统,因为你想等Root后能更新,要刷回官方rec才行。像我是在10时Root的。
5、确保root了后,不要双清或恢复系统出厂设置,因这样会去掉Root。
6、root后,因为上面教程提供的刷回原官方rec我猜是Meta7的或不知6P哪版本的,要确保完整,还是在花粉找到荣耀6plus对应系统版本的官方rec用fastboot工具包通过cmd命令行刷入,致于命令是什么,在你下Rec的贴下面有。
7、我用md5检测过,每个版本的rec是不同的检测识别的,所以请用有官方rec下载的版本Root效果更好,更安全。
希望我的经验对大家有用。
%2Fstorage%2Femulated%2F0%2FPictures%2FScreenshots%2FScreenshot_-00-17-13.jpeg (32.05 KB, 下载次数: 29)
09:07 上传
%2Fstorage%2Fsdcard1%2FPictures%2FScreenshots%2FIMG_343.jpg (28.87 KB, 下载次数: 31)
09:07 上传
%2Fstorage%2Fsdcard1%2FPictures%2FScreenshots%2FScreenshot_-16-01-53.jpeg (62.73 KB, 下载次数: 25)
09:07 上传
%2Fstorage%2Femulated%2F0%2FPictures%2FScreenshots%2FScreenshot_-09-44-23.jpeg (28.16 KB, 下载次数: 30)
09:07 上传
width:100%">
&神功盖世&
来自:浏览器
论坛因你更精彩。
width:100%">
&渐入佳境&
来自:浏览器
adm 项项更健康!!!
width:100%">
&新学乍练&
来自:浏览器
太棒了 谢谢
width:100%">
&炉火纯青&
来自:浏览器
哎呦不错这个屌
width:100%">
&登堂入室&
来自:浏览器
width:100%">
&禁止访问&
来自:浏览器
提示: 作者被禁止或删除 内容自动屏蔽
width:100%">
&独步江湖&
来自:浏览器
到底什么怎么样的?
width:100%">
&初窥门径&
来自:浏览器
我的解锁之后还是root不了
width:100%">
&初窥门径&
来自:浏览器
楼主 附件下载不了了
width:100%">
幸福黄昏M10升级手持拍摄夜景哟有一家民宿荣耀9i体检:夕阳与晨曦
花粉客户端
Make it Possible
Make your device special
华为云空间
Huawei cloud services
音乐播放器
Huawei Music
Huawei Vmall
关注花粉俱乐部
举报邮箱:
|关注花粉俱乐部:
增值电信业务经营许可证:苏B2-号|
Copyright (C)
华为软件技术有限公司 版权所有 保留一切权利404 Not Found
404 Not FoundJava加密技术
BASE64 严格地说,属于编码格式,而非加密算法MD5(Message Digest algorithm 5,信息摘要算法)SHA(Secure Hash Algorithm,安全散列算法)HMAC(Hash Message Authentication Code,散列消息鉴别码)
DES(Data Encryption Standard,数据加密算法)PBE(Password-based encryption,基于密码验证)RSA(算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman)DH(Diffie-Hellman算法,密钥一致协议)DSA(Digital Signature Algorithm,数字签名)ECC(Elliptic Curves Cryptography,椭圆曲线密码编码学)
& public static
byte[] decryptBASE64(String key)
throws Exception {& &&& return (new BASE64Decoder()).decodeBuffer(key);&
& public static String encryptBASE64(byte[] key)
throws Exception {& &&& return (new BASE64Encoder()).encodeBuffer(key);&
& public static
byte[] encryptMD5(byte[] data)
throws Exception {& & &&& MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);& &&& md5.update(data);& & &&& return md5.digest();& & }&
& &&& public static
byte[] encryptSHA(byte[] data)
throws Exception {& & &&&&&&& MessageDigest sha = MessageDigest.getInstance(KEY_SHA);&
&&&&&&& sha.update(data);& & &&&&&&& return sha.digest();& & &&& }& }&
& public static String initMacKey()
throws Exception {& &&& KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);&
& &&& SecretKey secretKey = keyGenerator.generateKey();& &&& return encryptBASE64(secretKey.getEncoded());&
& public static
byte[] encryptHMAC(byte[] data, String key)
throws Exception {& & &&& SecretKey secretKey = new SecretKeySpec(decryptBASE64(key), KEY_MAC);&
&&& Mac mac = Mac.getInstance(secretKey.getAlgorithm());& &&& mac.init(secretKey);& & &&& return mac.doFinal(data);& & }&
import java.security.MessageD&
& import javax.crypto.KeyG&
import javax.crypto.M& import javax.crypto.SecretK& & import sun.misc.BASE64D& import sun.misc.BASE64E& &
& public abstract
class Coder {& &&& public static
final String KEY_SHA = &SHA&;&
&&& public static
final String KEY_MD5 = &MD5&;&
& &&& public static
final String KEY_MAC = &HmacMD5&;&
& &&& public static
byte[] decryptBASE64(String key)
throws Exception {& &&&&&&& return (new BASE64Decoder()).decodeBuffer(key);&
&&& }& & &&&
& &&& public static String encryptBASE64(byte[] key)
throws Exception {& &&&&&&& return (new BASE64Encoder()).encodeBuffer(key);&
&&& }& & &&&
& &&& public static
byte[] encryptMD5(byte[] data)
throws Exception {& & &&&&&&& MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);&
&&&&&&& md5.update(data);& & &&&&&&& return md5.digest();& & &&& }& & &&&
& &&& public static
byte[] encryptSHA(byte[] data)
throws Exception {& & &&&&&&& MessageDigest sha = MessageDigest.getInstance(KEY_SHA);&
&&&&&&& sha.update(data);& & &&&&&&& return sha.digest();& & &&& }& & &&&
& &&& public static String initMacKey()
throws Exception {& &&&&&&& KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);&
& &&&&&&& SecretKey secretKey = keyGenerator.generateKey();& &&&&&&& return encryptBASE64(secretKey.getEncoded());&
&&& }& & &&&
& &&& public static
byte[] encryptHMAC(byte[] data, String key)
throws Exception {& & &&&&&&& SecretKey secretKey = new SecretKeySpec(decryptBASE64(key), KEY_MAC);&
&&&&&&& Mac mac = Mac.getInstance(secretKey.getAlgorithm());& &&&&&&& mac.init(secretKey);& & &&&&&&& return mac.doFinal(data);&
& &&& }& }&
import static org.junit.Assert.*;&
& import org.junit.T& &
& public class CoderTest {&
& &&& @Test& &&& public void test()
throws Exception {& &&&&&&& String inputStr = &简单加密&;& &&&&&&& System.err.println(&原文:\n& + inputStr);&
& &&&&&&& byte[] inputData = inputStr.getBytes();&
&&&&&&& String code = Coder.encryptBASE64(inputData);& & &&&&&&& System.err.println(&BASE64加密后:\n& + code);&
& &&&&&&& byte[] output = Coder.decryptBASE64(code);&
& &&&&&&& String outputStr = new String(output);&
& &&&&&&& System.err.println(&BASE64解密后:\n& + outputStr);&
& &&&&&&& & &&&&&&& assertEquals(inputStr, outputStr);& & &&&&&&& & &&&&&&& assertArrayEquals(Coder.encryptMD5(inputData), Coder& &&&&&&&&&&&&&&& .encryptMD5(inputData));& & &&&&&&& & &&&&&&& assertArrayEquals(Coder.encryptSHA(inputData), Coder& &&&&&&&&&&&&&&& .encryptSHA(inputData));& & &&&&&&& String key = Coder.initMacKey();& &&&&&&& System.err.println(&Mac密钥:\n& + key);&
& &&&&&&& &
&&&&&&& assertArrayEquals(Coder.encryptHMAC(inputData, key), Coder.encryptHMAC(&
&&&&&&&&&&&&&&& inputData, key));& & &&&&&&& BigInteger md5 = new BigInteger(Coder.encryptMD5(inputData));&
&&&&&&& System.err.println(&MD5:\n& + md5.toString(16));&
& &&&&&&& BigInteger sha = new BigInteger(Coder.encryptSHA(inputData));&
&&&&&&& System.err.println(&SHA:\n& + sha.toString(32));&
& &&&&&&& BigInteger mac = new BigInteger(Coder.encryptHMAC(inputData, inputStr));&
&&&&&&& System.err.println(&HMAC:\n& + mac.toString(16));&
Console代码&
原文:& 简单加密& BASE64加密后:& 566A5Y2V5Yqg5a+G& & BASE64解密后:& 简单加密& Mac密钥:& uGxdHC+6ylRDaik++leFtGwiMbuYUJ6mqHWyhSgF4trVkVBBSQvY/a22xU8XT1RUemdCWW155Bke&
pBIpkd7QHg==& & MD5:& -550b4d9de56& SHA:& 91k9vo7p400cjkgfhjh0ia9qthsjagfn& HMAC:& e95694bdbba2fa941009a&
警告:sun.misc.BASE64Decoder 是 Sun 的专用 API,可能会在未来版本中删除
import sun.misc.BASE64D
&&&&&&&&&&&&&& ^
警告:sun.misc.BASE64Encoder 是 Sun 的专用 API,可能会在未来版本中删除
import sun.misc.BASE64E
&&&&&&&&&&&&&& ^
接下来我们介绍对称加密算法,最常用的莫过于DES数据加密算法。
DES-Data Encryption Standard,即数据加密算法。是IBM公司于1975年研究成功并公开发表的。DES算法的入口参数有三个:Key、Data、Mode。其中Key为8个字节共64位,是DES算法的工作密钥;Data也为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密或解密。
  DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位。
通过java代码实现如下:Coder类见
import java.security.K& import java.security.SecureR&
& import javax.crypto.C& import javax.crypto.KeyG&
import javax.crypto.SecretK& import javax.crypto.SecretKeyF&
import javax.crypto.spec.DESKeyS&
& public abstract
class DESCoder extends Coder {&
& &&& public static
final String ALGORITHM = &DES&;&
& &&& private static Key toKey(byte[] key)
throws Exception {& &&&&&&& DESKeySpec dks = new DESKeySpec(key);&
&&&&&&& SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);&
&&&&&&& SecretKey secretKey = keyFactory.generateSecret(dks);& & &&&&&&& &
& &&&&&&& return secretK& &&& }& & &&&
& &&& public static
byte[] decrypt(byte[] data, String key)
throws Exception {& &&&&&&& Key k = toKey(decryptBASE64(key));& & &&&&&&& Cipher cipher = Cipher.getInstance(ALGORITHM);& &&&&&&& cipher.init(Cipher.DECRYPT_MODE, k);& & &&&&&&& return cipher.doFinal(data);&
&&& }& & &&&
& &&& public static
byte[] encrypt(byte[] data, String key)
throws Exception {& &&&&&&& Key k = toKey(decryptBASE64(key));& &&&&&&& Cipher cipher = Cipher.getInstance(ALGORITHM);& &&&&&&& cipher.init(Cipher.ENCRYPT_MODE, k);& & &&&&&&& return cipher.doFinal(data);&
&&& }& & &&&
& &&& public static String initKey()
throws Exception {& &&&&&&& return initKey(null);&
&&& }& & &&&
& &&& public static String initKey(String seed)
throws Exception {& &&&&&&& SecureRandom secureRandom = null;&
& &&&&&&& if (seed !=
null) {& &&&&&&&&&&& secureRandom = new SecureRandom(decryptBASE64(seed));&
&&&&&&& } else {& &&&&&&&&&&& secureRandom = new SecureRandom();&
&&&&&&& }& & &&&&&&& KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM);&
&&&&&&& kg.init(secureRandom);& & &&&&&&& SecretKey secretKey = kg.generateKey();& & &&&&&&& return encryptBASE64(secretKey.getEncoded());&
延续上一个类的实现,我们通过MD5以及SHA对字符串加密生成密钥,这是比较常见的密钥生成方式。
再给出一个测试类:
import static org.junit.Assert.*;&
& & import org.junit.T& &
& public class DESCoderTest {&
& &&& @Test& &&& public void test()
throws Exception {& &&&&&&& String inputStr = &DES&;& &&&&&&& String key = DESCoder.initKey();& &&&&&&& System.err.println(&原文:\t& + inputStr);&
& &&&&&&& System.err.println(&密钥:\t& + key);&
& &&&&&&& byte[] inputData = inputStr.getBytes();&
&&&&&&& inputData = DESCoder.encrypt(inputData, key);& & &&&&&&& System.err.println(&加密后:\t& + DESCoder.encryptBASE64(inputData));&
& &&&&&&& byte[] outputData = DESCoder.decrypt(inputData, key);&
&&&&&&& String outputStr = new String(outputData);&
& &&&&&&& System.err.println(&解密后:\t& + outputStr);&
& &&&&&&& assertEquals(inputStr, outputStr);& &&& }& }&
得到的输出内容如下:
Console代码&
原文: DES& 密钥: f3wEtRrV6q0=& & 加密后:&&& C6qe9oNIzRY=& & 解密后:&&& DES&
&&& 由控制台得到的输出,我们能够比对加密、解密后结果一致。这是一种简单的加密解密方式,只有一个密钥。
&&& 其实DES有很多同胞兄弟,如DESede(TripleDES)、AES、Blowfish、RC2、RC4(ARCFOUR)。这里就不过多阐述了,大同小异,只要换掉ALGORITHM换成对应的值,同时做一个代码替换SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);就可以了,此外就是密钥长度不同了。
/** * DES&&&&&&&&& key size must be equal to 56 * DESede(TripleDES) key size must be equal to 112 or 168
* AES&&&&&&&&& key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available
* Blowfish&&&& key size must be multiple of 8, and can only range from 32 to 448 (inclusive)
* RC2&&&&&&&&& key size must be between 40 and 1024 bits
* RC4(ARCFOUR) key size must be between 40 and 1024 bits
除了DES,我们还知道有DESede(TripleDES,就是3DES)、AES、Blowfish、RC2、RC4(ARCFOUR)等多种对称加密方式,其实现方式大同小异,这里介绍对称加密的另一个算法——PBE
&&& PBE——Password-based encryption(基于密码加密)。其特点在于口令由用户自己掌管,不借助任何物理媒体;采用随机数(这里我们叫做盐)杂凑多重加密等方法保证数据的安全性。是一种简便的加密方式。
通过java代码实现如下:Coder类见
import java.security.K& import java.util.R& & import javax.crypto.C& import javax.crypto.SecretK& import javax.crypto.SecretKeyF&
import javax.crypto.spec.PBEKeyS&
import javax.crypto.spec.PBEParameterS&
& public abstract
class PBECoder extends Coder {&
& &&& public static
final String ALGORITHM = &PBEWITHMD5andDES&;&
& &&& public static
byte[] initSalt() throws Exception {&
&&&&&&& byte[] salt =
new byte[8];&
&&&&&&& Random random = new Random();&
&&&&&&& random.nextBytes(salt);& &&&&&&& return& &&& }& & &&&
& &&& private static Key toKey(String password)
throws Exception {& &&&&&&& PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());&
&&&&&&& SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);&
&&&&&&& SecretKey secretKey = keyFactory.generateSecret(keySpec);&
& &&&&&&& return secretK& &&& }& & &&&
& &&& public static
byte[] encrypt(byte[] data, String password,
byte[] salt)& &&&&&&&&&&& throws Exception {& & &&&&&&& Key key = toKey(password);& & &&&&&&& PBEParameterSpec paramSpec = new PBEParameterSpec(salt,
100);& &&&&&&& Cipher cipher = Cipher.getInstance(ALGORITHM);& &&&&&&& cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);& & &&&&&&& return cipher.doFinal(data);&
& &&& }& & &&&
& &&& public static
byte[] decrypt(byte[] data, String password,
byte[] salt)& &&&&&&&&&&& throws Exception {& & &&&&&&& Key key = toKey(password);& & &&&&&&& PBEParameterSpec paramSpec = new PBEParameterSpec(salt,
100);& &&&&&&& Cipher cipher = Cipher.getInstance(ALGORITHM);& &&&&&&& cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);& & &&&&&&& return cipher.doFinal(data);&
& &&& }& }&
再给出一个测试类:
import static org.junit.Assert.*;&
& import org.junit.T& &
& public class PBECoderTest {&
& &&& @Test& &&& public void test()
throws Exception {& &&&&&&& String inputStr = &abc&;& &&&&&&& System.err.println(&原文: & + inputStr);&
&&&&&&& byte[] input = inputStr.getBytes();&
& &&&&&&& String pwd = &efg&;& &&&&&&& System.err.println(&密码: & + pwd);&
& &&&&&&& byte[] salt = PBECoder.initSalt();&
& &&&&&&& byte[] data = PBECoder.encrypt(input, pwd, salt);&
& &&&&&&& System.err.println(&加密后: & + PBECoder.encryptBASE64(data));&
& &&&&&&& byte[] output = PBECoder.decrypt(data, pwd, salt);&
&&&&&&& String outputStr = new String(output);&
& &&&&&&& System.err.println(&解密后: & + outputStr);&
&&&&&&& assertEquals(inputStr, outputStr);& &&& }& & }&
控制台输出:
Console代码&
原文: abc& 密码: efg& 加密后: iCZ0uRtaAhE=& & 解密后: abc&
&&& 后续我们会介绍非对称加密算法,如RSA、DSA、DH、ECC等。
接下来我们介绍典型的非对称加密算法——RSA
&&& 这种算法1978年就出现了,它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman。
&&& 这种加密算法的特点主要是密钥的变化,上文我们看到DES只有一个密钥。相当于只有一把钥匙,如果这把钥匙丢了,数据也就不安全了。RSA同时有两把钥匙,公钥与私钥。同时支持数字签名。数字签名的意义在于,对传输过来的数据进行校验。确保数据在传输工程中不被修改。
流程分析:
甲方构建密钥对儿,将公钥公布给乙方,将私钥保留。甲方使用私钥加密数据,然后用私钥对加密后的数据签名,发送给乙方签名以及加密后的数据;乙方使用公钥、签名来验证待解密数据是否有效,如果有效使用公钥对数据解密。乙方使用公钥加密数据,向甲方发送经过加密后的数据;甲方获得加密数据,通过私钥解密。
按如上步骤给出序列图,如下:
通过java代码实现如下:Coder类见
import java.security.K& import java.security.KeyF& import java.security.KeyP& import java.security.KeyPairG&
import java.security.PrivateK& import java.security.PublicK& import java.security.S& import java.security.interfaces.RSAPrivateK&
import java.security.interfaces.RSAPublicK&
import java.security.spec.PKCS8EncodedKeyS&
import java.security.spec.X509EncodedKeyS&
& import java.util.HashM& import java.util.M& & import javax.crypto.C& &
& public abstract
class RSACoder extends Coder {&
&&& public static
final String KEY_ALGORITHM = &RSA&;&
&&& public static
final String SIGNATURE_ALGORITHM =
&MD5withRSA&;& & &&& private static
final String PUBLIC_KEY = &RSAPublicKey&;&
&&& private static
final String PRIVATE_KEY = &RSAPrivateKey&;&
& &&& public static String sign(byte[] data, String privateKey)
throws Exception {& &&&&&&& & &&&&&&& byte[] keyBytes = decryptBASE64(privateKey);&
& &&&&&&& &
&&&&&&& PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);&
& &&&&&&& & &&&&&&& KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);&
& &&&&&&& & &&&&&&& PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);&
& &&&&&&& & &&&&&&& Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);&
&&&&&&& signature.initSign(priKey);& &&&&&&& signature.update(data);& & &&&&&&& return encryptBASE64(signature.sign());&
&&& }& & &&&
& &&& public static
boolean verify(byte[] data, String publicKey, String sign)&
&&&&&&&&&&& throws Exception {& & &&&&&&& & &&&&&&& byte[] keyBytes = decryptBASE64(publicKey);&
& &&&&&&& &
&&&&&&& X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);&
& &&&&&&& & &&&&&&& KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);&
& &&&&&&& & &&&&&&& PublicKey pubKey = keyFactory.generatePublic(keySpec);&
& &&&&&&& Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);&
&&&&&&& signature.initVerify(pubKey);& &&&&&&& signature.update(data);& & &&&&&&& & &&&&&&& return signature.verify(decryptBASE64(sign));&
&&& }& & &&&
& &&& public static
byte[] decryptByPrivateKey(byte[] data, String key)&
&&&&&&&&&&& throws Exception {& &&&&&&& & &&&&&&& byte[] keyBytes = decryptBASE64(key);&
& &&&&&&& & &&&&&&& PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);&
&&&&&&& KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);&
&&&&&&& Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);&
& &&&&&&& & &&&&&&& Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());&
&&&&&&& cipher.init(Cipher.DECRYPT_MODE, privateKey);& & &&&&&&& return cipher.doFinal(data);&
&&& }& & &&&
& &&& public static
byte[] decryptByPublicKey(byte[] data, String key)&
&&&&&&&&&&& throws Exception {& &&&&&&& & &&&&&&& byte[] keyBytes = decryptBASE64(key);&
& &&&&&&& & &&&&&&& X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);&
&&&&&&& KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);&
&&&&&&& Key publicKey = keyFactory.generatePublic(x509KeySpec);&
& &&&&&&& & &&&&&&& Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());&
&&&&&&& cipher.init(Cipher.DECRYPT_MODE, publicKey);& & &&&&&&& return cipher.doFinal(data);&
&&& }& & &&&
& &&& public static
byte[] encryptByPublicKey(byte[] data, String key)&
&&&&&&&&&&& throws Exception {& &&&&&&& & &&&&&&& byte[] keyBytes = decryptBASE64(key);&
& &&&&&&& & &&&&&&& X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);&
&&&&&&& KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);&
&&&&&&& Key publicKey = keyFactory.generatePublic(x509KeySpec);&
& &&&&&&& & &&&&&&& Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());&
&&&&&&& cipher.init(Cipher.ENCRYPT_MODE, publicKey);& & &&&&&&& return cipher.doFinal(data);&
&&& }& & &&&
& &&& public static
byte[] encryptByPrivateKey(byte[] data, String key)&
&&&&&&&&&&& throws Exception {& &&&&&&& & &&&&&&& byte[] keyBytes = decryptBASE64(key);&
& &&&&&&& & &&&&&&& PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);&
&&&&&&& KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);&
&&&&&&& Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);&
& &&&&&&& & &&&&&&& Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());&
&&&&&&& cipher.init(Cipher.ENCRYPT_MODE, privateKey);& & &&&&&&& return cipher.doFinal(data);&
&&& }& & &&&
& &&& public static String getPrivateKey(Map&String, Object& keyMap)&
&&&&&&&&&&& throws Exception {& &&&&&&& Key key = (Key) keyMap.get(PRIVATE_KEY);& & &&&&&&& return encryptBASE64(key.getEncoded());&
&&& }& & &&&
& &&& public static String getPublicKey(Map&String, Object& keyMap)&
&&&&&&&&&&& throws Exception {& &&&&&&& Key key = (Key) keyMap.get(PUBLIC_KEY);& & &&&&&&& return encryptBASE64(key.getEncoded());&
&&& }& & &&&
& &&& public static Map&String, Object& initKey()
throws Exception {& &&&&&&& KeyPairGenerator keyPairGen = KeyPairGenerator& &&&&&&&&&&&&&&& .getInstance(KEY_ALGORITHM);& &&&&&&& keyPairGen.initialize(1024);&
& &&&&&&& KeyPair keyPair = keyPairGen.generateKeyPair();& & &&&&&&& & &&&&&&& RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();&
& &&&&&&& & &&&&&&& RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();&
& &&&&&&& Map&String, Object& keyMap = new HashMap&String, Object&(2);&
& &&&&&&& keyMap.put(PUBLIC_KEY, publicKey);& &&&&&&& keyMap.put(PRIVATE_KEY, privateKey);& &&&&&&& return keyM& &&& }& }&
再给出一个测试类:
import static org.junit.Assert.*;&
& import org.junit.B& import org.junit.T& & import java.util.M& &
& public class RSACoderTest {&
&&& private String publicK& &&& private String privateK& & &&& @Before& &&& public void setUp()
throws Exception {& &&&&&&& Map&String, Object& keyMap = RSACoder.initKey();& & &&&&&&& publicKey = RSACoder.getPublicKey(keyMap);& &&&&&&& privateKey = RSACoder.getPrivateKey(keyMap);& &&&&&&& System.err.println(&公钥: \n\r& + publicKey);&
&&&&&&& System.err.println(&私钥: \n\r& + privateKey);&
&&& }& & &&& @Test& &&& public void test()
throws Exception {& &&&&&&& System.err.println(&公钥加密——私钥解密&);&
&&&&&&& String inputStr = &abc&;& &&&&&&& byte[] data = inputStr.getBytes();&
& &&&&&&& byte[] encodedData = RSACoder.encryptByPublicKey(data, publicKey);&
& &&&&&&& byte[] decodedData = RSACoder.decryptByPrivateKey(encodedData,&
&&&&&&&&&&&&&&& privateKey);& & &&&&&&& String outputStr = new String(decodedData);&
&&&&&&& System.err.println(&加密前: & + inputStr +
&\n\r& + &解密后: & + outputStr);&
&&&&&&& assertEquals(inputStr, outputStr);& & &&& }& & &&& @Test& &&& public void testSign()
throws Exception {& &&&&&&& System.err.println(&私钥加密——公钥解密&);&
&&&&&&& String inputStr = &sign&;& &&&&&&& byte[] data = inputStr.getBytes();&
& &&&&&&& byte[] encodedData = RSACoder.encryptByPrivateKey(data, privateKey);&
& &&&&&&& byte[] decodedData = RSACoder&
&&&&&&&&&&&&&&& .decryptByPublicKey(encodedData, publicKey);& & &&&&&&& String outputStr = new String(decodedData);&
&&&&&&& System.err.println(&加密前: & + inputStr +
&\n\r& + &解密后: & + outputStr);&
&&&&&&& assertEquals(inputStr, outputStr);& & &&&&&&& System.err.println(&私钥签名——公钥验证签名&);&
&&&&&&& & &&&&&&& String sign = RSACoder.sign(encodedData, privateKey);& &&&&&&& System.err.println(&签名:\r& + sign);&
& &&&&&&& & &&&&&&& boolean status = RSACoder.verify(encodedData, publicKey, sign);&
&&&&&&& System.err.println(&状态:\r& + status);&
&&&&&&& assertTrue(status);& & &&& }& & }&
控制台输出:
Console代码&
公钥:&& & MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYU/+I0+z1aBl5X6DUUOHQ7FZpmBSDbKTtx89J&
EcB64jFCkunELT8qiKly7fzEqD03g8ALlu5XvX+bBqHFy7YPJJP0ekE2X3wjUnh2NxlqpH3/B/xm&
1ZdSlCwDIkbijhBVDjA/bu5BObhZqQmDwIxlQInL9oVz+o6FbAZCyHBd7wIDAQAB&
& 私钥:&& & MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJhT/4jT7PVoGXlfoNRQ4dDsVmmY&
FINspO3Hz0kRwHriMUKS6cQtPyqIqXLt/MSoPTeDwAuW7le9f5sGocXLtg8kk/R6QTZffCNSeHY3&
GWqkff8H/GbVl1KULAMiRuKOEFUOMD9u7kE5uFmpCYPAjGVAicv2hXP6joVsBkLIcF3vAgMBAAEC&
gYBvZHWoZHmS2EZQqKqeuGr58eobG9hcZzWQoJ4nq/CarBAjw/VovUHE490uK3S9ht4FW7Yzg3LV&
/MB06Huifh6qf/X9NQA7SeZRRC8gnCQk6JuDIEVJOud5jU+9tyumJakDKodQ3Jf2zQtNr+5ZdEPl&
uwWgv9c4kmpjhAdyMuQmYQJBANn6pcgvyYaia52dnu+yBUsGkaFfwXkzFSExIbi0MXTkhEb/ER/D&
rLytukkUu5S5ecz/KBa8U4xIslZDYQbLz5ECQQCy5dutt7RsxN4+dxCWn0/1FrkWl2G329Ucewm3&
QU9CKu4D+7Kqdj+Ha3lXP8F0Etaaapi7+EfkRUpukn2ItZV/AkEAlk+I0iphxT1rCB0Q5CjWDY5S&
Df2B5JmdEG5Y2o0nLXwG2w44OLct/k2uD4cEcuITY5Dvi/4BftMCZwm/dnhEgQJACIktJSnJwxLV&
o9dchENPtlsCM9C/Sd2EWpqISSUlmfugZbJBwR5pQ5XeMUqKeXZYpP+HEBj1nS+tMH9u2/IGEwJA&
fL8mZiZXan/oBKrblAbplNcKWGRVD/3y65042PAEeghahlJMiYquV5DzZajuuT0wbJ5xQuZB01+X&
nfpFpBJ2dw==& & 公钥加密——私钥解密& 加密前: abc& & 解密后: abc& 公钥:&& & MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdOj40yEB48XqWxmPILmJAc7UecIN7F32etSHF&
9rwbuEh3+iTPOGSxhoSQpOED0vOb0ZIMkBXZSgsxLaBSin2RZ09YKWRjtpCA0kDkiD11gj4tzTiM&
l9qq1kwSK7ZkGAgodEn3yIILVmQDuEImHOXFtulvJ71ka07u3LuwUNdB/wIDAQAB&
& 私钥:&& & MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAN06PjTIQHjxepbGY8guYkBztR5w&
g3sXfZ61IcX2vBu4SHf6JM84ZLGGhJCk4QPS85vRkgyQFdlKCzEtoFKKfZFnT1gpZGO2kIDSQOSI&
PXWCPi3NOIyX2qrWTBIrtmQYCCh0SffIggtWZAO4QiYc5cW26W8nvWRrTu7cu7BQ10H/AgMBAAEC&
gYEAz2JWBizjI31bqhP4XiP9PuY5F3vqBW4T+L9cFbQiyumKJc58yzTWUAUGKIIn3enXLG7dNqGr&
mbJro4JeFIJ3CiVDpXR9+FluIgI4SXm7ioGKF2NOMA9LR5Fu82W+pLfpTN2y2SaLYWEDZyp53BxY&
j9gUxaxi1MQs+C1ZgDF2xmECQQDy70bQntbRfysP+ppCtd56YRnES1Tyekw0wryS2tr+ivQJl7JF&
gp5rPAOXpgrq36xHDwUspQ0sJ0vj0O7ywxr1AkEA6SAaLhrJJrYucC0jxwAhUYyaPN+aOsWymaRh&
9jA/Wc0wp29SbGTh5CcMuGpXm1g0M+FKW3dGiHgS3rVUKim4owJAbnxgapUzAgiiHxxMeDaavnHW&
9C2GrtjsO7qtZOTgYI/1uT8itvZW8lJTF+9OW8/qXE76fXl7ai9dFnl5kzMk2QJBALfHz/vCsArt&
mkRiwY6zApE4Z6tPl1V33ymSVovvUzHnOdD1SKQdD5t+UV/crb3QVi8ED0t2B0u0ZSPfDT/D7kMC&
QDpwdj9k2F5aokLHBHUNJPFDAp7a5QMaT64gv/d48ITJ68Co+v5WzLMpzJBYXK6PAtqIhxbuPEc2&
I2k1Afmrwyw=& & 私钥加密——公钥解密& 加密前: sign& & 解密后: sign& 私钥签名——公钥验证签名& 签名:& ud1RsIwmSC1pN22I4IXteg1VD2FbiehKUfNxgVSHzvQNIK+d20FCkHCqh9djP3h94iWnIUY0ifU+&
mbJkhAl/i5krExOE0hknOnPMcEP+lZV1RbJI2zG2YooSp2XDleqrQk5e/QF2Mx0Zxt8Xsg7ucVpn&
i3wwbYWs9wSzIf0UjlM=& & 状态:& true&
&&& 简要总结一下,使用公钥加密、私钥解密,完成了乙方到甲方的一次数据传递,通过私钥加密、公钥解密,同时通过私钥签名、公钥验证签名,完成了一次甲方到乙方的数据传递与验证,两次数据传递完成一整套的数据交互!
类似数字签名,数字信封是这样描述的:
  数字信封用加密技术来保证只有特定的收信人才能阅读信的内容。
&&& 信息发送方采用对称密钥来加密信息,然后再用接收方的公钥来加密此对称密钥(这部分称为数字信封),再将它和信息一起发送给接收方;接收方先用相应的私钥打开数字信封,得到对称密钥,然后使用对称密钥再解开信息。
接下来我们介绍DSA数字签名,非对称加密的另一种实现。
DSA-Digital Signature Algorithm 是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard)。简单的说,这是一种更高级的验证方式,用作数字签名。不单单只有公钥、私钥,还有数字签名。私钥加密生成数字签名,公钥验证数据及签名。如果数据和签名不匹配则认为验证失败!数字签名的作用就是校验数据在传输过程中不被修改。数字签名,是单向加密的升级!
通过java代码实现如下:Coder类见
import java.security.K& import java.security.KeyF& import java.security.KeyP& import java.security.KeyPairG&
import java.security.PrivateK& import java.security.PublicK& import java.security.SecureR&
import java.security.S& import java.security.interfaces.DSAPrivateK&
import java.security.interfaces.DSAPublicK&
import java.security.spec.PKCS8EncodedKeyS&
import java.security.spec.X509EncodedKeyS&
import java.util.HashM& import java.util.M& &
& public abstract
class DSACoder extends Coder {&
& &&& public static
final String ALGORITHM = &DSA&;&
& &&& private static
final int KEY_SIZE =
1024;& & &&&
& &&& private static
final String DEFAULT_SEED = &0f22507a10bbddd07d8ae3&;&
& &&& private static
final String PUBLIC_KEY = &DSAPublicKey&;&
&&& private static
final String PRIVATE_KEY = &DSAPrivateKey&;&
& &&& public static String sign(byte[] data, String privateKey)
throws Exception {& &&&&&&& & &&&&&&& byte[] keyBytes = decryptBASE64(privateKey);&
& &&&&&&& &
&&&&&&& PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);&
& &&&&&&& & &&&&&&& KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);&
& &&&&&&& & &&&&&&& PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);&
& &&&&&&& & &&&&&&& Signature signature = Signature.getInstance(keyFactory.getAlgorithm());&
&&&&&&& signature.initSign(priKey);& &&&&&&& signature.update(data);& & &&&&&&& return encryptBASE64(signature.sign());&
&&& }& & &&&
& &&& public static
boolean verify(byte[] data, String publicKey, String sign)&
&&&&&&&&&&& throws Exception {& & &&&&&&& & &&&&&&& byte[] keyBytes = decryptBASE64(publicKey);&
& &&&&&&& &
&&&&&&& X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);&
& &&&&&&& & &&&&&&& KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);&
& &&&&&&& & &&&&&&& PublicKey pubKey = keyFactory.generatePublic(keySpec);&
& &&&&&&& Signature signature = Signature.getInstance(keyFactory.getAlgorithm());&
&&&&&&& signature.initVerify(pubKey);& &&&&&&& signature.update(data);& & &&&&&&& & &&&&&&& return signature.verify(decryptBASE64(sign));&
&&& }& & &&&
& &&& public static Map&String, Object& initKey(String seed)
throws Exception {& &&&&&&& KeyPairGenerator keygen = KeyPairGenerator.getInstance(ALGORITHM);&
&&&&&&& & &&&&&&& SecureRandom secureRandom = new SecureRandom();&
&&&&&&& secureRandom.setSeed(seed.getBytes());& &&&&&&& keygen.initialize(KEY_SIZE, secureRandom);& & &&&&&&& KeyPair keys = keygen.genKeyPair();& & &&&&&&& DSAPublicKey publicKey = (DSAPublicKey) keys.getPublic();&
&&&&&&& DSAPrivateKey privateKey = (DSAPrivateKey) keys.getPrivate();&
& &&&&&&& Map&String, Object& map = new HashMap&String, Object&(2);&
&&&&&&& map.put(PUBLIC_KEY, publicKey);& &&&&&&& map.put(PRIVATE_KEY, privateKey);& & &&&&&&& return& &&& }& & &&&
& &&& public static Map&String, Object& initKey()
throws Exception {& &&&&&&& return initKey(DEFAULT_SEED);&
&&& }& & &&&
& &&& public static String getPrivateKey(Map&String, Object& keyMap)&
&&&&&&&&&&& throws Exception {& &&&&&&& Key key = (Key) keyMap.get(PRIVATE_KEY);& & &&&&&&& return encryptBASE64(key.getEncoded());&
&&& }& & &&&
& &&& public static String getPublicKey(Map&String, Object& keyMap)&
&&&&&&&&&&& throws Exception {& &&&&&&& Key key = (Key) keyMap.get(PUBLIC_KEY);& & &&&&&&& return encryptBASE64(key.getEncoded());&
再给出一个测试类:
import static org.junit.Assert.*;&
& import java.util.M& & import org.junit.T& &
& public class DSACoderTest {&
& &&& @Test& &&& public void test()
throws Exception {& &&&&&&& String inputStr = &abc&;& &&&&&&& byte[] data = inputStr.getBytes();&
& &&&&&&& & &&&&&&& Map&String, Object& keyMap = DSACoder.initKey();& & &&&&&&& & &&&&&&& String publicKey = DSACoder.getPublicKey(keyMap);& &&&&&&& String privateKey = DSACoder.getPrivateKey(keyMap);& & &&&&&&& System.err.println(&公钥:\r& + publicKey);&
&&&&&&& System.err.println(&私钥:\r& + privateKey);&
& &&&&&&& & &&&&&&& String sign = DSACoder.sign(data, privateKey);& &&&&&&& System.err.println(&签名:\r& + sign);&
& &&&&&&& & &&&&&&& boolean status = DSACoder.verify(data, publicKey, sign);&
&&&&&&& System.err.println(&状态:\r& + status);&
&&&&&&& assertTrue(status);& & &&& }& & }&
控制台输出:
Console代码&
公钥:& MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZp&
RV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fn&
xqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuE&
C/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJ&
FnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImo&
g9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAIu4RUlcQLp49PI0MrbssOY+3uySVnp0TULSv&
5T4VaHoKzsLHgGTrwOvsGA+V3yCNl2WDu3D84bSLF7liTWgOj+SMOEaPk4VyRTlLXZWGPsf1Mfd9&
21XAbMeVyKDSHHVGbMjBScajf3bXooYQMlyoHiOt/WrCo+mv7efstMM0PGo=& & 私钥:& MIIBTAIBADCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2&
USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4&
O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmC&
ouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCB&
gLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhR&
kImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoEFwIVAIegLUtmm2oQKQJTOiLugHTSjl/q&
& 签名:& MC0CFQCMg0J/uZmF8GuRpr3TNq48w60nDwIUJCyYNah+HtbU6NcQfy8Ac6LeLQs=&
& 状态:& true&
注意状态为true,就验证成功!
ECC-Elliptic Curves Cryptography,椭圆曲线密码编码学,是目前已知的公钥体制中,对每比特所提供加密强度最高的一种体制。在软件注册保护方面起到很大的作用,一般的序列号通常由该算法产生。
&&& 当我开始整理《Java加密技术(二)》的时候,我就已经在开始研究ECC了,但是关于Java实现ECC算法的资料实在是太少了,无论是国内还是国外的资料,无论是官方还是非官方的解释,最终只有一种答案——ECC算法在jdk1.5后加入支持,目前仅仅只能完成密钥的生成与解析。 如果想要获得ECC算法实现,需要调用硬件完成加密/解密(ECC算法相当耗费资源,如果单纯使用CPU进行加密/解密,效率低下),涉及到Java
Card领域,PKCS#11。 其实,PKCS#11配置很简单,但缺乏硬件设备,无法尝试!
&&& 尽管如此,我照旧提供相应的Java实现代码,以供大家参考。
通过java代码实现如下:Coder类见
import java.math.BigI& import java.security.K& import java.security.KeyF& import java.security.interfaces.ECPrivateK&
import java.security.interfaces.ECPublicK&
import java.security.spec.ECFieldF2m;&
import java.security.spec.ECParameterS&
import java.security.spec.ECP&
import java.security.spec.ECPrivateKeyS&
import java.security.spec.ECPublicKeyS&
import java.security.spec.EllipticC&
import java.security.spec.PKCS8EncodedKeyS&
import java.security.spec.X509EncodedKeyS&
import java.util.HashM& import java.util.M& & import javax.crypto.C& import javax.crypto.NullC& & import sun.security.ec.ECKeyF&
import sun.security.ec.ECPrivateKeyI&
import sun.security.ec.ECPublicKeyI&
& public abstract
class ECCCoder extends Coder {&
& &&& public static
final String ALGORITHM = &EC&;&
&&& private static
final String PUBLIC_KEY = &ECCPublicKey&;&
&&& private static
final String PRIVATE_KEY = &ECCPrivateKey&;&
& &&& public static
byte[] decrypt(byte[] data, String key)
throws Exception {& &&&&&&& & &&&&&&& byte[] keyBytes = decryptBASE64(key);&
& &&&&&&& & &&&&&&& PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);&
&&&&&&& KeyFactory keyFactory = ECKeyFactory.INSTANCE;& & &&&&&&& ECPrivateKey priKey = (ECPrivateKey) keyFactory& &&&&&&&&&&&&&&& .generatePrivate(pkcs8KeySpec);& & &&&&&&& ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(priKey.getS(),&
&&&&&&&&&&&&&&& priKey.getParams());& & &&&&&&& & &&&&&&& &
&&&&&&& Cipher cipher = new NullCipher();&
&&&&&&& cipher.init(Cipher.DECRYPT_MODE, priKey, ecPrivateKeySpec.getParams());&
& &&&&&&& return cipher.doFinal(data);&
&&& }& & &&&
& &&& public static
byte[] encrypt(byte[] data, String privateKey)&
&&&&&&&&&&& throws Exception {& &&&&&&& & &&&&&&& byte[] keyBytes = decryptBASE64(privateKey);&
& &&&&&&& & &&&&&&& X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);&
&&&&&&& KeyFactory keyFactory = ECKeyFactory.INSTANCE;& & &&&&&&& ECPublicKey pubKey = (ECPublicKey) keyFactory& &&&&&&&&&&&&&&& .generatePublic(x509KeySpec);& & &&&&&&& ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(pubKey.getW(),&
&&&&&&&&&&&&&&& pubKey.getParams());& & &&&&&&& & &&&&&&& &
&&&&&&& Cipher cipher = new NullCipher();&
&&&&&&& cipher.init(Cipher.ENCRYPT_MODE, pubKey, ecPublicKeySpec.getParams());&
& &&&&&&& return cipher.doFinal(data);&
&&& }& & &&&
& &&& public static String getPrivateKey(Map&String, Object& keyMap)&
&&&&&&&&&&& throws Exception {& &&&&&&& Key key = (Key) keyMap.get(PRIVATE_KEY);& & &&&&&&& return encryptBASE64(key.getEncoded());&
&&& }& & &&&
& &&& public static String getPublicKey(Map&String, Object& keyMap)&
&&&&&&&&&&& throws Exception {& &&&&&&& Key key = (Key) keyMap.get(PUBLIC_KEY);& & &&&&&&& return encryptBASE64(key.getEncoded());&
&&& }& & &&&
& &&& public static Map&String, Object& initKey()
throws Exception {& &&&&&&& BigInteger x1 = new BigInteger(&
&&&&&&&&&&&&&&& &2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8&,
16);& &&&&&&& BigInteger x2 = new BigInteger(&
&&&&&&&&&&&&&&& &d38ff536d538ccdaa3d9&,
16);& & &&&&&&& ECPoint g = new ECPoint(x1, x2);&
& &&&&&&& &
&&&&&&& BigInteger n = new BigInteger(&
&&&&&&&&&&&&&&& &3&,
10);& &&&&&&& & &&&&&&& int h = 2;&
&&&&&&& int m = 163;&
&&&&&&& int[] ks = {
7, 6, 3 };&
&&&&&&& ECFieldF2m ecField = new ECFieldF2m(m, ks);&
&&&&&&& & &&&&&&& BigInteger a = new BigInteger(&1&,
2);& &&&&&&& BigInteger b = new BigInteger(&1&,
2);& & &&&&&&& EllipticCurve ellipticCurve = new EllipticCurve(ecField, a, b);&
& &&&&&&& ECParameterSpec ecParameterSpec = new ECParameterSpec(ellipticCurve, g,&
&&&&&&&&&&&&&&& n, h);& &&&&&&& & &&&&&&& ECPublicKey publicKey = new ECPublicKeyImpl(g, ecParameterSpec);&
& &&&&&&& BigInteger s = new BigInteger(&
&&&&&&&&&&&&&&& &3&,
10);& &&&&&&& & &&&&&&& ECPrivateKey privateKey = new ECPrivateKeyImpl(s, ecParameterSpec);&
& &&&&&&& Map&String, Object& keyMap = new HashMap&String, Object&(2);&
& &&&&&&& keyMap.put(PUBLIC_KEY, publicKey);& &&&&&&& keyMap.put(PRIVATE_KEY, privateKey);& & &&&&&&& return keyM& &&& }& & }&
&&& 请注意上述代码中的TODO内容,再次提醒注意,Chipher不支持EC算法 ,以上代码仅供参考。Chipher、Signature、KeyPairGenerator、KeyAgreement、SecretKey均不支持EC算法。为了确保程序能够正常执行,我们使用了NullCipher类,验证程序。
照旧提供一个测试类:
import static org.junit.Assert.*;&
& import java.math.BigI& import java.security.spec.ECFieldF2m;&
import java.security.spec.ECParameterS&
import java.security.spec.ECP&
import java.security.spec.ECPrivateKeyS&
import java.security.spec.ECPublicKeyS&
import java.security.spec.EllipticC&
import java.util.M& & import org.junit.T& &
& public class ECCCoderTest {&
& &&& @Test& &&& public void test()
throws Exception {& &&&&&&& String inputStr = &abc&;& &&&&&&& byte[] data = inputStr.getBytes();&
& &&&&&&& Map&String, Object& keyMap = ECCCoder.initKey();& & &&&&&&& String publicKey = ECCCoder.getPublicKey(keyMap);& &&&&&&& String privateKey = ECCCoder.getPrivateKey(keyMap);& &&&&&&& System.err.println(&公钥: \n& + publicKey);&
&&&&&&& System.err.println(&私钥: \n& + privateKey);&
& &&&&&&& byte[] encodedData = ECCCoder.encrypt(data, publicKey);&
& &&&&&&& byte[] decodedData = ECCCoder.decrypt(encodedData, privateKey);&
& &&&&&&& String outputStr = new String(decodedData);&
&&&&&&& System.err.println(&加密前: & + inputStr +
&\n\r& + &解密后: & + outputStr);&
&&&&&&& assertEquals(inputStr, outputStr);& &&& }& }&
控制台输出:
Console代码&
公钥:&& MEAwEAYHKoZIzj0CAQYFK4EEAAEDLAAEAv4TwFN7vBGsqgfXk95ObV5clO7oAokHD7BdOP9YMh8u&
gAU21TjM2qPZ& & 私钥:&& MDICAQAwEAYHKoZIzj0CAQYFK4EEAAEEGzAZAgEBBBTYJsR3BN7TFw7JHcAHFkwNmfil7w==&
& 加密前: abc& & 解密后: abc&
博客分类:
&&& 本篇的主要内容为Java证书体系的实现。
请大家在阅读本篇内容时先阅读 ,预先了解RSA加密算法。
在构建Java代码实现前,我们需要完成证书的制作。
1.生成keyStroe文件
在命令行下执行以下命令:
Shell代码&
keytool -genkey -validity 36000 -alias www.zlex.org -keyalg RSA -keystore d:\zlex.keystore&
-genkey表示生成密钥
-validity指定证书有效期,这里是36000天
-alias指定别名,这里是www.zlex.org
-keyalg指定算法,这里是RSA
-keystore指定存储位置,这里是d:\zlex.keystore
在这里我使用的密码为 123456
控制台输出:
Console代码&
输入keystore密码:& 再次输入新密码:& 您的名字与姓氏是什么?& & [Unknown]:& www.zlex.org& 您的组织单位名称是什么?& & [Unknown]:& zlex& 您的组织名称是什么?& & [Unknown]:& zlex& 您所在的城市或区域名称是什么?& & [Unknown]:& BJ& 您所在的州或省份名称是什么?& & [Unknown]:& BJ& 该单位的两字母国家代码是什么& & [Unknown]:& CN& CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN 正确吗?& & [否]:& Y& & 输入&tomcat&的主密码& &&&&&&& (如果和 keystore 密码相同,按回车):& 再次输入新密码:&
这时,在D盘下会生成一个zlex.keystore的文件。
2.生成自签名证书
光有keyStore文件是不够的,还需要证书文件,证书才是直接提供给外界使用的公钥凭证。
导出证书:
Shell代码&
keytool -export -keystore d:\zlex.keystore -alias www.zlex.org -file d:\zlex.cer -rfc&
-export指定为导出操作
-keystore指定keystore文件
-alias指定导出keystore文件中的别名
-file指向导出路径
-rfc以文本格式输出,也就是以BASE64编码输出
这里的密码是 123456
控制台输出:
Console代码&
输入keystore密码:& 保存在文件中的认证 &d:\zlex.cer&&
当然,使用方是需要导入证书的!
可以通过自签名证书完成CAS单点登录系统的构建!
Ok,准备工作完成,开始Java实现!
通过java代码实现如下:Coder类见
import java.io.FileInputS& import java.security.KeyS& import java.security.PrivateK& import java.security.PublicK& import java.security.S& import java.security.cert.C&
import java.security.cert.CertificateF&
import java.security.cert.X509C&
import java.util.D& & import javax.crypto.C& &
& public abstract
class CertificateCoder extends Coder {&
& &&& public static
final String KEY_STORE = &JKS&;&
& &&& public static
final String X509 = &X.509&;&
& &&& private static PrivateKey getPrivateKey(String keyStorePath, String alias,&
&&&&&&&&&&& String password) throws Exception {&
&&&&&&& KeyStore ks = getKeyStore(keyStorePath, password);& &&&&&&& PrivateKey key = (PrivateKey) ks.getKey(alias, password.toCharArray());&
&&&&&&& return& &&& }& & &&&
& &&& private static PublicKey getPublicKey(String certificatePath)&
&&&&&&&&&&& throws Exception {& &&&&&&& Certificate certificate = getCertificate(certificatePath);&
&&&&&&& PublicKey key = certificate.getPublicKey();& &&&&&&& return& &&& }& & &&&
& &&& private static Certificate getCertificate(String certificatePath)&
&&&&&&&&&&& throws Exception {& &&&&&&& CertificateFactory certificateFactory = CertificateFactory&
&&&&&&&&&&&&&&& .getInstance(X509);& &&&&&&& FileInputStream in = new FileInputStream(certificatePath);&
& &&&&&&& Certificate certificate = certificateFactory.generateCertificate(in);&
&&&&&&& in.close();& & &&&&&&& return& &&& }& & &&&
& &&& private static Certificate getCertificate(String keyStorePath,&
&&&&&&&&&&& String alias, String password) throws Exception {&
&&&&&&& KeyStore ks = getKeyStore(keyStorePath, password);& &&&&&&& Certificate certificate = ks.getCertificate(alias);& & &&&&&&& return& &&& }& & &&&
& &&& private static KeyStore getKeyStore(String keyStorePath, String password)&
&&&&&&&&&&& throws Exception {& &&&&&&& FileInputStream is = new FileInputStream(keyStorePath);&
&&&&&&& KeyStore ks = KeyStore.getInstance(KEY_STORE);& &&&&&&& ks.load(is, password.toCharArray());& &&&&&&& is.close();& &&&&&&& return& &&& }& & &&&
& &&& public static
byte[] encryptByPrivateKey(byte[] data, String keyStorePath,&
&&&&&&&&&&& String alias, String password) throws Exception {&
&&&&&&& & &&&&&&& PrivateKey privateKey = getPrivateKey(keyStorePath, alias, password);&
& &&&&&&& & &&&&&&& Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());&
&&&&&&& cipher.init(Cipher.ENCRYPT_MODE, privateKey);& & &&&&&&& return cipher.doFinal(data);&
& &&& }& & &&&
& &&& public static
byte[] decryptByPrivateKey(byte[] data, String keyStorePath,&
&&&&&&&&&&& String alias, String password) throws Exception {&
&&&&&&& & &&&&&&& PrivateKey privateKey = getPrivateKey(keyStorePath, alias, password);&
& &&&&&&& & &&&&&&& Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());&
&&&&&&& cipher.init(Cipher.DECRYPT_MODE, privateKey);& & &&&&&&& return cipher.doFinal(data);&
& &&& }& & &&&
& &&& public static
byte[] encryptByPublicKey(byte[] data, String certificatePath)&
&&&&&&&&&&& throws Exception {& & &&&&&&& & &&&&&&& PublicKey publicKey = getPublicKey(certificatePath);& &&&&&&& & &&&&&&& Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());&
&&&&&&& cipher.init(Cipher.ENCRYPT_MODE, publicKey);& & &&&&&&& return cipher.doFinal(data);&
& &&& }& & &&&
& &&& public static
byte[] decryptByPublicKey(byte[] data, String certificatePath)&
&&&&&&&&&&& throws Exception {& &&&&&&& & &&&&&&& PublicKey publicKey = getPublicKey(certificatePath);& & &&&&&&& & &&&&&&& Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());&
&&&&&&& cipher.init(Cipher.DECRYPT_MODE, publicKey);& & &&&&&&& return cipher.doFinal(data);&
& &&& }& & &&&
& &&& public static
boolean verifyCertificate(String certificatePath) {&
&&&&&&& return verifyCertificate(new Date(), certificatePath);&
&&& }& & &&&
& &&& public static
boolean verifyCertificate(Date date, String certificatePath) {&
&&&&&&& boolean status =
true;& &&&&&&& try {& &&&&&&&&&&& & &&&&&&&&&&& Certificate certificate = getCertificate(certificatePath);&
&&&&&&&&&&& & &&&&&&&&&&& status = verifyCertificate(date, certificate);& &&&&&&& } catch (Exception e) {& &&&&&&&&&&& status = false;& &&&&&&& }& &&&&&&& return& &&& }& & &&&
& &&& private static
boolean verifyCertificate(Date date, Certificate certificate) {&
&&&&&&& boolean status =
true;& &&&&&&& try {& &&&&&&&&&&& X509Certificate x509Certificate = (X509Certificate)&
&&&&&&&&&&& x509Certificate.checkValidity(date);& &&&&&&& } catch (Exception e) {& &&&&&&&&&&& status = false;& &&&&&&& }& &&&&&&& return& &&& }& & &&&
& &&& public static String sign(byte[] sign, String keyStorePath, String alias,&
&&&&&&&&&&& String password) throws Exception {&
&&&&&&& & &&&&&&& X509Certificate x509Certificate = (X509Certificate) getCertificate(&
&&&&&&&&&&&&&&& keyStorePath, alias, password);& &&&&&&& & &&&&&&& KeyStore ks = getKeyStore(keyStorePath, password);& &&&&&&& & &&&&&&& PrivateKey privateKey = (PrivateKey) ks.getKey(alias, password&
&&&&&&&&&&&&&&& .toCharArray());& & &&&&&&& & &&&&&&& Signature signature = Signature.getInstance(x509Certificate&
&&&&&&&&&&&&&&& .getSigAlgName());& &&&&&&& signature.initSign(privateKey);& &&&&&&& signature.update(sign);& &&&&&&& return encryptBASE64(signature.sign());&
&&& }& & &&&
& &&& public static
boolean verify(byte[] data, String sign,&
&&&&&&&&&&& String certificatePath) throws Exception {&
&&&&&&& & &&&&&&& X509Certificate x509Certificate = (X509Certificate) getCertificate(certificatePath);&
&&&&&&& & &&&&&&& PublicKey publicKey = x509Certificate.getPublicKey();& &&&&&&& & &&&&&&& Signature signature = Signature.getInstance(x509Certificate&
&&&&&&&&&&&&&&& .getSigAlgName());& &&&&&&& signature.initVerify(publicKey);& &&&&&&& signature.update(data);& & &&&&&&& return signature.verify(decryptBASE64(sign));&
& &&& }& & &&&
& &&& public static
boolean verifyCertificate(Date date, String keyStorePath,&
&&&&&&&&&&& String alias, String password) {& &&&&&&& boolean status =
true;& &&&&&&& try {& &&&&&&&&&&& Certificate certificate = getCertificate(keyStorePath, alias,&
&&&&&&&&&&&&&&&&&&& password);& &&&&&&&&&&& status = verifyCertificate(date, certificate);& &&&&&&& } catch (Exception e) {& &&&&&&&&&&& status = false;& &&&&&&& }& &&&&&&& return& &&& }& & &&&
& &&& public static
boolean verifyCertificate(String keyStorePath, String alias,&
&&&&&&&&&&& String password) {& &&&&&&& return verifyCertificate(new Date(), keyStorePath, alias, password);&
再给出一个测试类:
import static org.junit.Assert.*;&
& import org.junit.T& &
& public class CertificateCoderTest {&
&&& private String password =
&123456&;& &&& private String alias =
&www.zlex.org&;& &&& private String certificatePath =
&d:/zlex.cer&;& &&& private String keyStorePath =
&d:/zlex.keystore&;& & &&& @Test& &&& public void test()
throws Exception {& &&&&&&& System.err.println(&公钥加密——私钥解密&);&
&&&&&&& String inputStr = &Ceritifcate&;&
&&&&&&& byte[] data = inputStr.getBytes();&
& &&&&&&& byte[] encrypt = CertificateCoder.encryptByPublicKey(data,&
&&&&&&&&&&&&&&& certificatePath);& & &&&&&&& byte[] decrypt = CertificateCoder.decryptByPrivateKey(encrypt,&
&&&&&&&&&&&&&&& keyStorePath, alias, password);& &&&&&&& String outputStr = new String(decrypt);&
& &&&&&&& System.err.println(&加密前: & + inputStr +
&\n\r& + &解密后: & + outputStr);&
& &&&&&&& & &&&&&&& assertArrayEquals(data, decrypt);& & &&&&&&& & &&&&&&& assertTrue(CertificateCoder.verifyCertificate(certificatePath));&
& &&& }& & &&& @Test& &&& public void testSign()
throws Exception {& &&&&&&& System.err.println(&私钥加密——公钥解密&);&
& &&&&&&& String inputStr = &sign&;& &&&&&&& byte[] data = inputStr.getBytes();&
& &&&&&&& byte[] encodedData = CertificateCoder.encryptByPrivateKey(data,&
&&&&&&&&&&&&&&& keyStorePath, alias, password);& & &&&&&&& byte[] decodedData = CertificateCoder.decryptByPublicKey(encodedData,&
&&&&&&&&&&&&&&& certificatePath);& & &&&&&&& String outputStr = new String(decodedData);&
&&&&&&& System.err.println(&加密前: & + inputStr +
&\n\r& + &解密后: & + outputStr);&
&&&&&&& assertEquals(inputStr, outputStr);& & &&&&&&& System.err.println(&私钥签名——公钥验证签名&);&
&&&&&&& & &&&&&&& String sign = CertificateCoder.sign(encodedData, keyStorePath, alias,&
&&&&&&&&&&&&&&& password);& &&&&&&& System.err.println(&签名:\r& + sign);&
& &&&&&&& & &&&&&&& boolean status = CertificateCoder.verify(encodedData, sign,&
&&&&&&&&&&&&&&& certificatePath);& &&&&&&& System.err.println(&状态:\r& + status);&
&&&&&&& assertTrue(status);& & &&& }& }&
控制台输出:
Console代码&
公钥加密——私钥解密& 加密前: Ceritificate& & 解密后: Ceritificate& & 私钥加密——公钥解密& 加密前: sign& & 解密后: sign& 私钥签名——公钥验证签名& 签名:& pqBn5m6PJlfOjH0A6U2o2mUmBsfgyEY1NWCbiyA/I5Gc3gaVNVIdj/zkGNZRqTjhf3+J9a9z9EI7&
6F2eWYd7punHx5oh6hfNgcKbVb52EfItl4QEN+djbXiPynn07+Lbg1NOjULnpEd6ZhLP1YwrEAuM&
OfvX0e7/wplxLbySaKQ=& & 状态:& true&
由此完成了证书验证体系!
同样,我们可以对代码做签名——代码签名!
通过工具JarSigner可以完成代码签名。
这里我们对tools.jar做代码签名,命令如下:
Shell代码&
jarsigner -storetype jks -keystore zlex.keystore -verbose tools.jar www.zlex.org&
控制台输出:
Console代码&
输入密钥库的口令短语:& 正在更新: META-INF/WWW_ZLEX.SF& 正在更新: META-INF/WWW_ZLEX.RSA& & 正在签名: org/zlex/security/Security.class& & 正在签名: org/zlex/tool/Main$1.class&
& 正在签名: org/zlex/tool/Main$2.class&
& 正在签名: org/zlex/tool/Main.class& & 警告:& 签名者证书将在六个月内过期。&
此时,我们可以对签名后的jar做验证!
验证tools.jar,命令如下:
Shell代码&
jarsigner -verify -verbose -certs tools.jar&
控制台输出:
Console代码&
&&&&&&&& 402 Sat Jun 20
16:25:14 CST
2009 META-INF/MANIFEST.MF& &&&&&&&& 532 Sat Jun 20
16:25:14 CST
2009 META-INF/WWW_ZLEX.SF& &&&&&&&& 889 Sat Jun 20
16:25:14 CST
2009 META-INF/WWW_ZLEX.RSA& sm&&&&&& 590 Wed Dec 10
13:03:42 CST
2008 org/zlex/security/Security.class& & &&&&& X.509, CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN&
&&&&& [证书将在 09-9-18 下午3:27 到期]&
& sm&&&&&& 705 Tue Dec 16
18:00:56 CST
2008 org/zlex/tool/Main$1.class&
& &&&&& X.509, CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN&
&&&&& [证书将在 09-9-18 下午3:27 到期]&
& sm&&&&&& 779 Tue Dec 16
18:00:56 CST
2008 org/zlex/tool/Main$2.class&
& &&&&& X.509, CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN&
&&&&& [证书将在 09-9-18 下午3:27 到期]&
& sm&&&& 12672 Tue Dec 16
18:00:56 CST
2008 org/zlex/tool/Main.class& & &&&&& X.509, CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN&
&&&&& [证书将在 09-9-18 下午3:27 到期]&
& & & s = 已验证签名& & m = 在清单中列出条目& & k = 在密钥库中至少找到了一个证书& & i = 在身份作用域内至少找到了一个证书& & jar 已验证。& & 警告:& 此 jar 包含签名者证书将在六个月内过期的条目。&
代码签名认证的用途主要是对发布的软件做验证,支持 Sun Java .jar (Java Applet) 文件(J2SE)和 J2ME MIDlet Suite 文件。
博客分类:
&&& 在中,我们模拟了一个基于RSA非对称加密网络的安全通信。现在我们深度了解一下现有的安全网络通信——SSL。
&&& 我们需要构建一个由CA机构签发的有效证书,这里我们使用上文中生成的自签名证书zlex.cer
&&& 这里,我们将证书导入到我们的密钥库。
Shell代码&
keytool -import -alias www.zlex.org -file d:/zlex.cer -keystore d:/zlex.keystore&
-import表示导入
-alias指定别名,这里是www.zlex.org
-file指定算法,这里是d:/zlex.cer
-keystore指定存储位置,这里是d:/zlex.keystore
在这里我使用的密码为654321
控制台输出:
Console代码&
输入keystore密码:& 再次输入新密码:& 所有者:CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN& 签发人:CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN& 序列号:4a1e48df& 有效期: Thu May 28 16:18:39 CST
2009 至Wed Aug 26
16:18:39 CST
2009& 证书指纹:& &&&&&&&& MD5:19:CA:E6:36:E2:DF:AD:96:31:97:2F:A9:AD:FC:37:6A&
&&&&&&&& SHA1:49:88:30:59:29:45:F1:69:CA:97:A9:6D:8A:CF:08:D2:C3:D5:C0:C4&
&&&&&&&& 签名算法名称:SHA1withRSA& &&&&&&&& 版本: 3& 信任这个认证? [否]:& y& 认证已添加至keystore中&
OK,最复杂的准备工作已经完成。
接下来我们将域名www.zlex.org定位到本机上。打开C:\Windows\System32\drivers\etc\hosts文件,将www.zlex.org绑定在本机上。在文件末尾追加127.0.0.1&&&&&& www.zlex.org。现在通过地址栏访问,或者通过ping命令,如果能够定位到本机,域名映射就搞定了。
现在,配置tomcat。先将zlex.keystore拷贝到tomcat的conf目录下,然后配置server.xml。将如下内容加入配置文件
&&& SSLEnabled=&true&&
&&& URIEncoding=&UTF-8&&
&&& clientAuth=&false&&
&&& keystoreFile=&conf/zlex.keystore&&
&&& keystorePass=&123456&&
&&& maxThreads=&150&&
&&& port=&443&&
&&& protocol=&HTTP/1.1&&
&&& scheme=&https&&
&&& secure=&true&&
&&& sslProtocol=&TLS&
注意clientAuth=&false&测试阶段,置为false,正式使用时建议使用true。现在启动tomcat,访问。
显然,证书未能通过认证,这个时候你可以选择安装证书(上文中的zlex.cer文件就是证书),作为受信任的根证书颁发机构导入,再次重启浏览器(IE,其他浏览器对于域名www.zlex.org不支持本地方式访问),访问,你会看到地址栏中会有个小锁,就说明安装成功。所有的浏览器联网操作已经在RSA加密解密系统的保护之下了。但似乎我们感受不到。
这个时候很多人开始怀疑,如果我们要手工做一个这样的https的访问是不是需要把浏览器的这些个功能都实现呢?不需要!
接着上篇内容,给出如下代码实现

我要回帖

更多关于 华为P9root 的文章

 

随机推荐