签名算法
我們使用非對(duì)稱加密算法的時(shí)候,對(duì)于一個(gè)公鑰-私鑰對(duì),通常是用公鑰加密,私鑰解密。
如果使用私鑰加密,公鑰解密是否可行呢?實(shí)際上是完全可行的。
不過我們?cè)僮屑?xì)想一想,私鑰是保密的,而公鑰是公開的,用私鑰加密,那相當(dāng)于所有人都可以用公鑰解密。這個(gè)加密有什么意義?
這個(gè)加密的意義在于,如果小明用自己的私鑰加密了一條消息,比如小明喜歡小紅,然后他公開了加密消息,由于任何人都可以用小明的公鑰解密,從而使得任何人都可以確認(rèn)小明喜歡小紅這條消息肯定是小明發(fā)出的,其他人不能偽造這個(gè)消息,小明也不能抵賴這條消息不是自己寫的。
因此,私鑰加密得到的密文實(shí)際上就是數(shù)字簽名,要驗(yàn)證這個(gè)簽名是否正確,只能用私鑰持有者的公鑰進(jìn)行解密驗(yàn)證。使用數(shù)字簽名的目的是為了確認(rèn)某個(gè)信息確實(shí)是由某個(gè)發(fā)送方發(fā)送的,任何人都不可能偽造消息,并且,發(fā)送方也不能抵賴。
在實(shí)際應(yīng)用的時(shí)候,簽名實(shí)際上并不是針對(duì)原始消息,而是針對(duì)原始消息的哈希進(jìn)行簽名,即:
signature = encrypt(privateKey, sha256(message))
對(duì)簽名進(jìn)行驗(yàn)證實(shí)際上就是用公鑰解密:
hash = decrypt(publicKey, signature)
然后把解密后的哈希與原始消息的哈希進(jìn)行對(duì)比。
因?yàn)橛脩艨偸鞘褂米约旱乃借€進(jìn)行簽名,所以,私鑰就相當(dāng)于用戶身份。而公鑰喲用來給外部驗(yàn)證用戶身份。
常用數(shù)字簽名算法有:
- MD5withRSA
- SHA1withRSA
- SHA256withRSA
它們實(shí)際上就是制定某種哈希算法進(jìn)行RSA簽名的方式。
import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security;public class Main {public static void main(String[] args) throws GeneralSecurityException {// 生成RSA公鑰/私鑰:KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");kpGen.initialize(1024);KeyPair kp = kpGen.generateKeyPair();PrivateKey sk = kp.getPrivate();PublicKey pk = kp.getPublic();// 待簽名的消息:byte[] message = "Hello, I am Bob!".getBytes(StandardCharsets.UTF_8);// 用私鑰簽名:Signature s = Signature.getInstance("SHA1withRSA");s.initSign(sk);s.update(message);byte[] signed = s.sign();System.out.println(String.format("signature: %x", new BigInteger(1, signed)));// 用公鑰驗(yàn)證:Signature v = Signature.getInstance("SHA1withRSA");v.initVerify(pk);v.udpate(message);boolean valid = v.verify(signed);System.out.println("valid? " + valid);} }使用其他公鑰,或者驗(yàn)證簽名的時(shí)候修改原始信息,都無法驗(yàn)證成功。
DSA簽名
除了RSA可以簽名外,還可以使用DSA算法進(jìn)行簽名。DSA是Digital Signature Algorithm的縮寫,它使用ElGamal數(shù)字簽名算法。
DSA只能配合SHA使用,常用的算法有:
- SHA1withDSA
- SHA256withDSA
- SHA512withDSA
和RSA數(shù)字簽名相比,DSA的優(yōu)點(diǎn)是更快。
ECDSA簽名
橢圓曲線簽名算法ECDSA:Elliptic Curve Digital Signature Algorithm也是一種常用的簽名算法,它的特點(diǎn)是可以從私鑰推出公鑰。比特幣的簽名算法就采用了ECDSA算法,使用標(biāo)準(zhǔn)橢圓曲線secp256k1。BouncyCastle提供了ECDSA的完整實(shí)現(xiàn)。
小結(jié)
數(shù)字簽名就是用發(fā)送方的私鑰對(duì)原始數(shù)據(jù)進(jìn)行簽名,只有用發(fā)送方公鑰才能通過簽名驗(yàn)證。
數(shù)字簽名用于:
- 防止偽造;
- 防止抵賴;
- 檢測(cè)篡改。
常用的數(shù)字簽名算法包括:MD5withRSA/SHA1withRSA/SHA256withRSA/SHA1withDSA/SHA256withDSA/SHA512withDSA/ECDSA等。
總結(jié)
- 上一篇: java验证生日的正则表达式
- 下一篇: cookie的expires属性和max