java.security.Provider 原始碼學習筆記

X_Shadow發表於2019-01-19

java.security.Provider

內部類Service

/**
* Construct a new service.
*
* @param provider     提供本服務的Provider
* @param type         服務的型別
* @param algorithm     演算法名稱
* @param className     本服務的實現類的名稱
* @param aliases     別名列表|空(如果服務沒有別名)
* @param attributes 屬性對映|空(如果實現沒有屬性)
*
* @throws NullPointerException if provider, type, algorithm, or
* className is null
*/
public Service(Provider provider, String type, String algorithm,
    String className, List<String> aliases, Map<String,String> attributes)

以BC的RSA演算法為例toString()輸出的結果

BC: Cipher.RSA -> org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi$NoPadding
  aliases: [RSA//RAW, RSA//NOPADDING]
  attributes: {SupportedKeyFormats=PKCS#8|X.509, SupportedKeyClasses=javax.crypto.interfaces.RSAPublicKey|javax.crypto.interfaces.RSAPrivateKey}

BC: Cipher.RSA/OAEP -> org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi$OAEPPadding
  aliases: [RSA//OAEPPADDING]

其中:

  • Service.className = org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi$NoPadding
  • Service.type = Cipher
  • Service.algorithm = RSA

檢視支援的金鑰型別:

public boolean supportsParameter(Object parameter)

attributes:SupportedKeyFormats=PKCS#8|X.509

繼承Properties類

函式put<key,value>:

Key=

  • type.algorithm
  • type.oid
  • type.OID.oid
  • Alg.Alias.type.algorithm
  • Alg.Alias.type.oid
  • Alg.Alias.type.OID.oid

value = className

  • key = type.algorithm(前三種),value是spi類的全路徑名稱
  • key = 帶有Alg.Alias..(後三種),value = type.algorithm中的algorithm.

方法

  • 返回Provider中所有的property條目Set<Key,Value>

    public synchronized Set<Map.Entry<Object,Object>> entrySet()
    
    
  • 返回Provider中所有的Property條目中的Set<Key>

    public Set<Object> keySet() 
    
  • 返回Provider中所有的Property條目中的Collection<Key>

    public Collection<Object> values()
    
  • 根據Type和algorithm獲取Service

    public synchronized Service getService(String type, String algorithm)
    
  • 繼承自Property的函式

    新增
    public synchronized Object put(Object key, Object value)
    public synchronized void putAll(Map<?,?> t)
    
    刪除
    public synchronized Object remove(Object key)
    public synchronized void clear()
    
    獲取
    public Object get(Object key)
    public String getProperty(String key)
    

type,algorithm到service的轉換

provider.put(key,value)
name = key,value = value
private void parseLegacyPut(String name, String value) {
    if (name.toLowerCase(ENGLISH).startsWith(ALIAS_PREFIX_LOWER)) {
        // e.g. put("Alg.Alias.MessageDigest.SHA", "SHA-1");
        // aliasKey ~ MessageDigest.SHA
        String stdAlg = value;
        String aliasKey = name.substring(ALIAS_LENGTH);
        String[] typeAndAlg = getTypeAndAlgorithm(aliasKey);
        if (typeAndAlg == null) {
            return;
        }
        String type = getEngineName(typeAndAlg[0]);
        String aliasAlg = typeAndAlg[1].intern();
        ServiceKey key = new ServiceKey(type, stdAlg, true);
        Service s = legacyMap.get(key);
        if (s == null) {
            s = new Service(this);
            s.type = type;
            s.algorithm = stdAlg;
            legacyMap.put(key, s);
        }
        legacyMap.put(new ServiceKey(type, aliasAlg, true), s);
        s.addAlias(aliasAlg);
    } else {
        String[] typeAndAlg = getTypeAndAlgorithm(name);
        if (typeAndAlg == null) {
            return;
        }
        int i = typeAndAlg[1].indexOf(` `);
        if (i == -1) {
            // e.g. put("MessageDigest.SHA-1", "sun.security.provider.SHA");
            String type = getEngineName(typeAndAlg[0]);
            String stdAlg = typeAndAlg[1].intern();
            String className = value;
            ServiceKey key = new ServiceKey(type, stdAlg, true);
            Service s = legacyMap.get(key);
            if (s == null) {
                s = new Service(this);
                s.type = type;
                s.algorithm = stdAlg;
                legacyMap.put(key, s);
            }
            s.className = className;
        } else { // attribute
            // e.g. put("MessageDigest.SHA-1 ImplementedIn", "Software");
            String attributeValue = value;
            String type = getEngineName(typeAndAlg[0]);
            String attributeString = typeAndAlg[1];
            String stdAlg = attributeString.substring(0, i).intern();
            String attributeName = attributeString.substring(i + 1);
            // kill additional spaces
            while (attributeName.startsWith(" ")) {
                attributeName = attributeName.substring(1);
            }
            attributeName = attributeName.intern();
            ServiceKey key = new ServiceKey(type, stdAlg, true);
            Service s = legacyMap.get(key);
            if (s == null) {
                s = new Service(this);
                s.type = type;
                s.algorithm = stdAlg;
                legacyMap.put(key, s);
            }
            s.addAttribute(attributeName, attributeValue);
        }
    }
}

呼叫parseLegacyPut(),實際是將type,algorithm等轉換成Map<ServiceKey,Service> legacyMap;

引擎類在getInstance()的時候去呼叫Provider.getService(type,algorithm)方法,通過ServiceKey(type,algorithm)獲取到Service.
然後在引擎類的getInstance()中呼叫service.newInstance()返回引擎類spi的例項

相關文章