签名算法
我們使用非對稱加密算法的時候,對于一個公鑰-私鑰對,通常是用公鑰加密,私鑰解密。
如果使用私鑰加密,公鑰解密是否可行呢?實際上是完全可行的。
不過我們再仔細(xì)想一想,私鑰是保密的,而公鑰是公開的,用私鑰加密,那相當(dāng)于所有人都可以用公鑰解密。這個加密有什么意義?
這個加密的意義在于,如果小明用自己的私鑰加密了一條消息,比如小明喜歡小紅,然后他公開了加密消息,由于任何人都可以用小明的公鑰解密,從而使得任何人都可以確認(rèn)小明喜歡小紅這條消息肯定是小明發(fā)出的,其他人不能偽造這個消息,小明也不能抵賴這條消息不是自己寫的。
因此,私鑰加密得到的密文實際上就是數(shù)字簽名,要驗證這個簽名是否正確,只能用私鑰持有者的公鑰進(jìn)行解密驗證。使用數(shù)字簽名的目的是為了確認(rèn)某個信息確實是由某個發(fā)送方發(fā)送的,任何人都不可能偽造消息,并且,發(fā)送方也不能抵賴。
在實際應(yīng)用的時候,簽名實際上并不是針對原始消息,而是針對原始消息的哈希進(jìn)行簽名,即:
signature = encrypt(privateKey, sha256(message))
對簽名進(jìn)行驗證實際上就是用公鑰解密:
hash = decrypt(publicKey, signature)
然后把解密后的哈希與原始消息的哈希進(jìn)行對比。
因為用戶總是使用自己的私鑰進(jìn)行簽名,所以,私鑰就相當(dāng)于用戶身份。而公鑰喲用來給外部驗證用戶身份。
常用數(shù)字簽名算法有:
- MD5withRSA
- SHA1withRSA
- SHA256withRSA
它們實際上就是制定某種哈希算法進(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)));// 用公鑰驗證:Signature v = Signature.getInstance("SHA1withRSA");v.initVerify(pk);v.udpate(message);boolean valid = v.verify(signed);System.out.println("valid? " + valid);} }使用其他公鑰,或者驗證簽名的時候修改原始信息,都無法驗證成功。
DSA簽名
除了RSA可以簽名外,還可以使用DSA算法進(jìn)行簽名。DSA是Digital Signature Algorithm的縮寫,它使用ElGamal數(shù)字簽名算法。
DSA只能配合SHA使用,常用的算法有:
- SHA1withDSA
- SHA256withDSA
- SHA512withDSA
和RSA數(shù)字簽名相比,DSA的優(yōu)點是更快。
ECDSA簽名
橢圓曲線簽名算法ECDSA:Elliptic Curve Digital Signature Algorithm也是一種常用的簽名算法,它的特點是可以從私鑰推出公鑰。比特幣的簽名算法就采用了ECDSA算法,使用標(biāo)準(zhǔn)橢圓曲線secp256k1。BouncyCastle提供了ECDSA的完整實現(xiàn)。
小結(jié)
數(shù)字簽名就是用發(fā)送方的私鑰對原始數(shù)據(jù)進(jìn)行簽名,只有用發(fā)送方公鑰才能通過簽名驗證。
數(shù)字簽名用于:
- 防止偽造;
- 防止抵賴;
- 檢測篡改。
常用的數(shù)字簽名算法包括:MD5withRSA/SHA1withRSA/SHA256withRSA/SHA1withDSA/SHA256withDSA/SHA512withDSA/ECDSA等。
總結(jié)
- 上一篇: java验证生日的正则表达式
- 下一篇: cookie的expires属性和max