Java 里的 MessageDigest、Cipher、Signature 是怎么找到具体实现的?这篇看提供者列表与顺序、算法名的解析、错误信息,再自己写一个提供者验证优先级(KeyStore 与 PKIX 在后面的篇目,JSSE 的握手见前面)。
已安装的提供者(按优先级):
1. SUN 版本 21,提供 55 个服务
2. SunRsaSign 版本 21,提供 19 个服务
3. SunEC 版本 21,提供 42 个服务
4. SunJSSE 版本 21,提供 15 个服务
5. SunJCE 版本 21,提供 179 个服务
6. SunJGSS 版本 21,提供 2 个服务
7. SunSASL 版本 21,提供 8 个服务
8. XMLDSig 版本 21,提供 13 个服务
9. SunPCSC 版本 21,提供 1 个服务
10. JdkLDAP 版本 21,提供 1 个服务
11. JdkSASL 版本 21,提供 2 个服务
12. Apple 版本 21,提供 1 个服务
13. SunPKCS11 版本 21,提供 0 个服务
java.security 里的配置:security.provider.1 = SUN,security.provider.2 = SunRsaSign
MessageDigest.getInstance("SHA-256") 用的提供者 = SUN
Cipher.getInstance("AES/GCM/NoPadding") 用的提供者 = SunJCE
KeyFactory.getInstance("RSA") = SunRsaSign;Signature.getInstance("SHA256withECDSA") = SunEC;SecureRandom 默认 = SUN MessageDigest.getInstance("SHA-256" ) → 成功,getAlgorithm = SHA-256
MessageDigest.getInstance("SHA256" ) → 成功,getAlgorithm = SHA256
MessageDigest.getInstance("SHA-1" ) → 成功,getAlgorithm = SHA-1
MessageDigest.getInstance("SHA1" ) → 成功,getAlgorithm = SHA1
MessageDigest.getInstance("2.16.840.1.101.3.4.2.1" ) → 成功,getAlgorithm = 2.16.840.1.101.3.4.2.1
MessageDigest.getInstance("Sha-256" ) → 成功,getAlgorithm = Sha-256
MessageDigest.getInstance("SHA-999" ) → NoSuchAlgorithmException: SHA-999 MessageDigest not available
指定一个不存在的提供者 → NoSuchProviderException: no such provider: NoSuchProvider
指定的提供者没有这个算法(SunJCE 里没有 SHA-256)→ NoSuchAlgorithmException: no such algorithm: SHA-256 for provider SunJCE
Cipher.getInstance("AES") 的默认转换(不写模式与填充)实际是 AES;加密 16 字节后的密文长度 = 32(ECB + PKCS5Padding) 安装自定义提供者之前:SHA-256 的提供者 = SUN
addProvider(MyProvider)(加在末尾):SHA-256 的提供者 = SUN,MyProvider 的位置 = 14
insertProviderAt(MyProvider, 1) 返回 1:SHA-256 的提供者 = MyProvider
[MyProvider] 我的 SHA-256 实现被调用了
调用 digest 的结果(前 4 字节)= 2cf24dba,与直接用 SUN 的结果一致:true
指定 "SUN" 的 getInstance 不受优先级影响:SUN
removeProvider 之后:SHA-256 的提供者 = SUN