你的位置:首页 > Java教程

[Java教程]java加密类型和算法名称


    项目里有各种加密方法,但从来没有仔细研究过。一般只是copy。这几天遇到一些问题,看了一下加密代码,觉得有些疑惑。

    我们知道jdk已经为我们包装好了很多的算法。但究竟包装了哪些算法,怎么去掉这些算法我并没有去查过。今天跟了一下源码,大概知道了。

    首先要从下面这几行代码说起:

KeyGenerator kgen = KeyGenerator.getInstance("AES");SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");

    对于AES加密,我们用KeyGenerator kgen = KeyGenerator.getInstance("AES");,MD5我们用java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");,这里从方法上看出java类是通过一个算法名称去找的,比如AES,但源码中并没有把算法名称包装为枚举,我们无法得知KeyGenerator除了有AES算法,还能获得那些算法,而且如何获得KeyGenerator的算法名称,比如AES不全是大写会不会有问题,KeyGenerator是不是有MD5等等。

    打开KeyGenerator.getInstance()方法,看其源码

 

public static final KeyGenerator getInstance(String paramString)  throws NoSuchAlgorithmException {  return new KeyGenerator(paramString); }

 

    我们发现直接调用了构造方法,查看构造方法:

 private KeyGenerator(String paramString)  throws NoSuchAlgorithmException {  this.algorithm = paramString;    List localList = GetInstance.getServices("KeyGenerator", paramString);  this.serviceIterator = localList.iterator();  this.initType = 1;  if (nextSpi(null, false) == null) {   throw new NoSuchAlgorithmException(paramString + " KeyGenerator not available");  }  if ((!skipDebug) && (pdebug != null)) {   pdebug.println("KeyGenerator." + paramString + " algorithm from: " + this.provider    .getName());  } } 

    构造方法其实是通过GetInstance.getServices("KeyGenerator", paramString)去找到,继续跟进

 public Provider.Service getService(String paramString1, String paramString2) {  for (int i = 0; i < this.configs.length; i++)  {   Provider localProvider = getProvider(i);   Provider.Service localService = localProvider.getService(paramString1, paramString2);   if (localService != null) {    return localService;   }  }  return null; }

    GetInstance.getServices其实是遍历所有的Provider,然后按顺序返回第一个有这个算法服务的Provide的算法服务(Provider.Service)。这里可以看出,寻找服务需要两个参数,第一个参数是type,比如"KeyGenerator",第二个是算法名称,“AES”。那现在我们只要知道有哪些Provide,每个Provide里有哪些Provider.Service就可以了。

    在jdk的API中,查看 KeyGenerator.getInstance方法,其中给了我们提示:

 

    我们可以本地写一个方法遍历jdk所有的算法:

package com.hongkang.test;import java.security.Provider;import java.security.Security;import java.security.Provider.Service;public class TestSecurity {  public static void main(String[] args) {    Provider[] providers = Security.getProviders();    for(Provider p:providers){      System.out.println("provider name:"+p.getName());      for(Service s:p.getServices()){        System.out.println("类型:"+s.getType()+",算法:"+s.getAlgorithm());      }      System.out.println("--------------------------");    }  }}

输出结果:

provider name:SUN类型:SecureRandom,算法:SHA1PRNG类型:Signature,算法:SHA1withDSA类型:Signature,算法:NONEwithDSA类型:KeyPairGenerator,算法:DSA类型:MessageDigest,算法:MD2类型:MessageDigest,算法:MD5类型:MessageDigest,算法:SHA类型:MessageDigest,算法:SHA-256类型:MessageDigest,算法:SHA-384类型:MessageDigest,算法:SHA-512类型:AlgorithmParameterGenerator,算法:DSA类型:AlgorithmParameters,算法:DSA类型:KeyFactory,算法:DSA类型:CertificateFactory,算法:X.509类型:KeyStore,算法:JKS类型:KeyStore,算法:CaseExactJKS类型:Policy,算法:JavaPolicy类型:Configuration,算法:JavaLoginConfig类型:CertPathBuilder,算法:PKIX类型:CertPathValidator,算法:PKIX类型:CertStore,算法:LDAP类型:CertStore,算法:Collection类型:CertStore,算法:com.sun.security.IndexedCollection--------------------------provider name:SunRsaSign类型:KeyFactory,算法:RSA类型:KeyPairGenerator,算法:RSA类型:Signature,算法:MD2withRSA类型:Signature,算法:MD5withRSA类型:Signature,算法:SHA1withRSA类型:Signature,算法:SHA256withRSA类型:Signature,算法:SHA384withRSA类型:Signature,算法:SHA512withRSA--------------------------provider name:SunEC类型:KeyFactory,算法:EC类型:AlgorithmParameters,算法:EC类型:Signature,算法:NONEwithECDSA类型:Signature,算法:SHA1withECDSA类型:Signature,算法:SHA256withECDSA类型:Signature,算法:SHA384withECDSA类型:Signature,算法:SHA512withECDSA类型:KeyPairGenerator,算法:EC类型:KeyAgreement,算法:ECDH--------------------------provider name:SunJSSE类型:KeyFactory,算法:RSA类型:KeyPairGenerator,算法:RSA类型:Signature,算法:MD2withRSA类型:Signature,算法:MD5withRSA类型:Signature,算法:SHA1withRSA类型:Signature,算法:MD5andSHA1withRSA类型:KeyManagerFactory,算法:SunX509类型:KeyManagerFactory,算法:NewSunX509类型:TrustManagerFactory,算法:SunX509类型:TrustManagerFactory,算法:PKIX类型:SSLContext,算法:TLSv1类型:SSLContext,算法:TLSv1.1类型:SSLContext,算法:TLSv1.2类型:SSLContext,算法:Default类型:KeyStore,算法:PKCS12--------------------------provider name:SunJCE类型:Cipher,算法:RSA类型:Cipher,算法:DES类型:Cipher,算法:DESede类型:Cipher,算法:DESedeWrap类型:Cipher,算法:PBEWithMD5AndDES类型:Cipher,算法:PBEWithMD5AndTripleDES类型:Cipher,算法:PBEWithSHA1AndRC2_40类型:Cipher,算法:PBEWithSHA1AndDESede类型:Cipher,算法:Blowfish类型:Cipher,算法:AES类型:Cipher,算法:AESWrap类型:Cipher,算法:RC2类型:Cipher,算法:ARCFOUR类型:KeyGenerator,算法:DES类型:KeyGenerator,算法:DESede类型:KeyGenerator,算法:Blowfish类型:KeyGenerator,算法:AES类型:KeyGenerator,算法:RC2类型:KeyGenerator,算法:ARCFOUR类型:KeyGenerator,算法:HmacMD5类型:KeyGenerator,算法:HmacSHA1类型:KeyGenerator,算法:HmacSHA256类型:KeyGenerator,算法:HmacSHA384类型:KeyGenerator,算法:HmacSHA512类型:KeyPairGenerator,算法:DiffieHellman类型:AlgorithmParameterGenerator,算法:DiffieHellman类型:KeyAgreement,算法:DiffieHellman类型:AlgorithmParameters,算法:DiffieHellman类型:AlgorithmParameters,算法:DES类型:AlgorithmParameters,算法:DESede类型:AlgorithmParameters,算法:PBE类型:AlgorithmParameters,算法:PBEWithMD5AndDES类型:AlgorithmParameters,算法:PBEWithMD5AndTripleDES类型:AlgorithmParameters,算法:PBEWithSHA1AndDESede类型:AlgorithmParameters,算法:PBEWithSHA1AndRC2_40类型:AlgorithmParameters,算法:Blowfish类型:AlgorithmParameters,算法:AES类型:AlgorithmParameters,算法:RC2类型:AlgorithmParameters,算法:OAEP类型:KeyFactory,算法:DiffieHellman类型:SecretKeyFactory,算法:DES类型:SecretKeyFactory,算法:DESede类型:SecretKeyFactory,算法:PBEWithMD5AndDES类型:SecretKeyFactory,算法:PBEWithMD5AndTripleDES类型:SecretKeyFactory,算法:PBEWithSHA1AndDESede类型:SecretKeyFactory,算法:PBEWithSHA1AndRC2_40类型:SecretKeyFactory,算法:PBKDF2WithHmacSHA1类型:Mac,算法:HmacMD5类型:Mac,算法:HmacSHA1类型:Mac,算法:HmacSHA256类型:Mac,算法:HmacSHA384类型:Mac,算法:HmacSHA512类型:Mac,算法:HmacPBESHA1类型:Mac,算法:SslMacMD5类型:Mac,算法:SslMacSHA1类型:KeyStore,算法:JCEKS类型:KeyGenerator,算法:SunTlsPrf类型:KeyGenerator,算法:SunTls12Prf类型:KeyGenerator,算法:SunTlsMasterSecret类型:KeyGenerator,算法:SunTlsKeyMaterial类型:KeyGenerator,算法:SunTlsRsaPremasterSecret--------------------------provider name:SunJGSS类型:GssApiMechanism,算法:1.2.840.113554.1.2.2类型:GssApiMechanism,算法:1.3.6.1.5.5.2--------------------------provider name:SunSASL类型:SaslClientFactory,算法:DIGEST-MD5类型:SaslClientFactory,算法:NTLM类型:SaslClientFactory,算法:GSSAPI类型:SaslClientFactory,算法:EXTERNAL类型:SaslClientFactory,算法:PLAIN类型:SaslClientFactory,算法:CRAM-MD5类型:SaslServerFactory,算法:CRAM-MD5类型:SaslServerFactory,算法:GSSAPI类型:SaslServerFactory,算法:DIGEST-MD5类型:SaslServerFactory,算法:NTLM--------------------------provider name://www.w3.org/2002/06/类型:TransformService,算法:http://www.w3.org/2000/09/类型:TransformService,算法:http://www.w3.org/2001/10/类型:TransformService,算法:http://www.w3.org/2001/10/类型:TransformService,算法:http://www.w3.org/TR/2001/REC-类型://www.w3.org/2006/12/类型:TransformService,算法:http://www.w3.org/2000/09/类型:TransformService,算法:http://www.w3.org/TR/2001/REC-类型:TransformService,算法:http://www.w3.org/TR/1999/REC-xpath-19991116类型:TransformService,算法:http://www.w3.org/TR/1999/REC-xslt-19991116类型:TransformService,算法:http://www.w3.org/2006/12/类型:KeyInfoFactory,算法:DOM--------------------------provider name:SunPCSC类型:TerminalFactory,算法:PC/SC--------------------------provider name:SunMSCAPI类型:SecureRandom,算法:Windows-PRNG类型:KeyStore,算法:Windows-MY类型:KeyStore,算法:Windows-ROOT类型:Signature,算法:NONEwithRSA类型:Signature,算法:SHA1withRSA类型:Signature,算法:SHA256withRSA类型:Signature,算法:SHA384withRSA类型:Signature,算法:SHA512withRSA类型:Signature,算法:MD5withRSA类型:Signature,算法:MD2withRSA类型:KeyPairGenerator,算法:RSA类型:Cipher,算法:RSA类型:Cipher,算法:RSA/ECB/PKCS1Padding--------------------------

通过观察,我们发现算法的类型,基本都对应java的一个类。算法类基本在jce.jar和rt.jar中。从这个结果中我们基本就能自己找算法了,比如要用MD5,在上面列表中发现类型是MessageDigest,则

MessageDigest md5 = MessageDigest.getInstance("MD5");

再仔细查看java.security.Provider类源码,发现此类在初始时就已经将这些算法类型初始化了,

 static {  addEngine("AlgorithmParameterGenerator", false, null);  addEngine("AlgorithmParameters", false, null);  addEngine("KeyFactory", false, null);  addEngine("KeyPairGenerator", false, null);  addEngine("KeyStore", false, null);  addEngine("MessageDigest", false, null);  addEngine("SecureRandom", false, null);  addEngine("Signature", true, null);  addEngine("CertificateFactory", false, null);  addEngine("CertPathBuilder", false, null);  addEngine("CertPathValidator", false, null);  addEngine("CertStore", false, "java.security.cert.CertStoreParameters");  addEngine("Cipher", true, null);  addEngine("ExemptionMechanism", false, null);  addEngine("Mac", true, null);  addEngine("KeyAgreement", true, null);  addEngine("KeyGenerator", false, null);  addEngine("SecretKeyFactory", false, null);  addEngine("KeyManagerFactory", false, null);  addEngine("SSLContext", false, null);  addEngine("TrustManagerFactory", false, null);  addEngine("GssApiMechanism", false, null);  addEngine("SaslClientFactory", false, null);  addEngine("SaslServerFactory", false, null);  addEngine("Policy", false, "java.security.Policy$Parameters");  addEngine("Configuration", false, "javax.security.auth.login.Configuration$Parameters");  addEngine("false, null);  addEngine("KeyInfoFactory", false, null);  addEngine("TransformService", false, null);  addEngine("TerminalFactory", false, "java.lang.Object"); }

//还对大小写做了容错处理
  private static void addEngine(String paramString1, boolean paramBoolean, String paramString2)
  {
    EngineDescription localEngineDescription = new EngineDescription(paramString1, paramBoolean, paramString2);
    knownEngines.put(paramString1.toLowerCase(Locale.ENGLISH), localEngineDescription);
    knownEngines.put(paramString1, localEngineDescription);
  }

不过遗憾的是并没有找到AES这类算法是怎么初始化的。但是经测试,即便使用的不是大写,或者上面列表中列出的标准写法,也能正常获取,比如:

KeyGenerator kgen = KeyGenerator.getInstance("aEs");

也能正常执行。