數字簽名的原理以下所示, 灰色的 原文件、公鑰、加密後的摘要 是要發送給對方的。html
對方驗證的過程是 用原文件生成摘要1, 同時用公鑰解密 加密後的摘要 獲得 摘要2, 而後對比摘要1 和 摘要2 是否相同。java
咱們使用keytool 生成的keystore 文件裏存儲了私鑰和公鑰信息,因此因此簽名apk時 須要提供 keystore 文件。打包工具集裏的jarsigner、 signapk 等工具會提取其中的私鑰、公鑰來使用。git
公鑰存在CERT.RSA 證書中,存放於apk 的 META-INFO/CERT.RSA .算法
(原文:http://www.educity.cn/wenda/124033.html)
keytool -genkey -alias test -keyalg RSA -keystore c:/key.store
生成keyStore
RSA是一個既能用於數據加密也能用於數字簽名的算法。
DSA(Digital Signature Algorithm,數字簽名算法,用做數字簽名標準的一部分),它是另外一種公開密鑰算法,它不能用做加密,只用做數字簽名。DSA使用公開密鑰,爲接受者驗證數據的完整性和數據發送者的身份。
提取證書:
經過keytool命令咱們能夠很輕鬆的提取證書.
證書包括主體信息,公鑰.
keytool -export -alias 別名 -keystore 文件名 -file 證書名稱
可是咱們沒法經過KEYTOOL工具來提取私鑰的..咱們只能經過java的 KeyStore 類getEntry() 或者getKey()來提取私鑰.
讀取keyStore文件:工具
char[] password = "password".toCharArray();
java.io.FileInputStream fis = new java.io.FileInputStream("c:/server/server_keystore");
//從指定的輸入流中加載此 KeyStore
ks.load(fis, password);
//keystore 中的每一項都用「別名」字符串標識。
//使用指定保護參數獲取指定別名的 keystore Entry。
//KeyStore.PrivateKeyEntry 保存 PrivateKey 和相應證書鏈的 KeyStore 項。
//方法1.
KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) ks.getEntry( "keystore別名",
new KeyStore.PasswordProtection(password) );
// 返回與給定別名相關聯的密鑰
//方法2.
PrivateKey key = (PrivateKey) ks.getKey("ser", password);
加密
怎麼來驗證提取的私鑰是否正確呢 (由於公鑰私鑰必須成對出現,咱們能夠經過證書提取去公鑰,而後用公鑰加密,使用剛剛得到的私鑰解密)
提取證書的方法:
keytool -export -alias 別名 -keystore 文件名 -file 證書名稱
spa
//經過證書,獲取公鑰
CertificateFactory cf = CertificateFactory.getInstance("X.509");
FileInputStream in = new FileInputStream("C:\\server\\server.cer");
//生成一個證書對象並使用從輸入流 inStream 中讀取的數據對它進行初始化。
Certificate c = cf.generateCertificate(in);
PublicKey publicKey = c.getPublicKey();
//經過下面這段代碼提取的私鑰是否正確
String before = "asdf";
byte[] plainText = before.getBytes("UTF-8");
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
// 用公鑰進行加密,返回一個字節流
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] cipherText = cipher.doFinal(plainText);
// 用私鑰進行解密,返回一個字節流
cipher.init(Cipher.DECRYPT_MODE, myPrivateKey);
byte[] newPlainText = cipher.doFinal(cipherText);
// 若是newPlainText 和 before 相同的話,那麼私鑰和公鑰是配對的
System.out.println(new String(newPlainText, "UTF-8"));
code