Java安全——提供者相關的體系架構
標籤(空格分隔): Java 安全
[toc]
安全提供者
Java的安全軟體特性,是通過安全軟體包的概念透出的。換句話說,安全領域常見的鑑別、加密、簽名等概念,在Java中的支援是通過安全軟體包來實現的。Java對於安全軟體包的定義其實是一組抽象介面。Sun作為Java的作者,提供了一組實現。而安全軟體包是由安全提供者、演算法和引擎組成的。引擎可以理解為一組操作,演算法定義了操作如何執行,而安全提供者則負責實現這兩個抽象概念。
比如說,訊息摘要是一個引擎,它是程式設計師能執行的一個操作。訊息摘要的思想與如何計算訊息摘要沒有關係,所有的訊息摘要具備同樣的特性,因此抽象出來的介面就是引擎。而實現訊息摘要可以有MD5和SHA等演算法,演算法由具體類實現。而安全提供者就是二者的橋樑,用來管理引擎和演算法。安全提供者的目的就是提供一個簡單的機制,從而可以方便的改變或替換演算法及其實現。因此,通過安全提供者,程式設計師只需要使用引擎的介面,而不需要關係具體哪個類實現了演算法,演算法由哪個安全提供者提供。
體系結構
Java安全軟體包的體系結構可以總結為四個部分:
引擎
JVM提供引擎類,是Java核心API的一部分。
演算法
針對每一種引擎,都會有一組演算法實現。Java提供了一組預設的演算法實現(由Sun提供),第三方的機構可以提供其他實現。
提供者
演算法類是由提供者來管理的,提供者知道如何將演算法與實現的具體類對應起來。
安全類
安全類儲存提供者列表,可以通過安全類檢視有哪些提供者,以及它們提供的演算法支援有哪些。
安全提供者體系的一個流程如下:
業務類->引擎: 呼叫某個介面
引擎->安全類: 詢問
安全類->提供者: 找到提供者
提供者->演算法: 找到對應演算法
演算法->業務類:返回計算結果
以MessageDigest的getInstance()方法為例,發現其實是呼叫Security.getImpl()方法實現的,而內部又是通過
GetInstance.getInstance
(type, getSpiClass(type), algorithm, params, provider).toArray();
這樣的語句來做的。而這個GetInstance會返回一個Instance物件,其類宣告如下:
public static final class Instance {
public final Provider provider;
public final Object impl;
private Instance(Provider arg0, Object arg1) {
this.provider = arg0;
this.impl = arg1;
}
public Object[] toArray() {
return new Object[] {this.impl, this.provider};
}
}
可見就是一個Provider和Object(具體演算法)的封裝。
提供者選擇
JVM在啟動時,會去$JREHOME/lib/security/java.security中註冊提供者。以我個人電腦中的檔案為例:
#
# List of providers and their preference orders (see above):
#
security.provider.1=sun.security.provider.Sun
security.provider.2=sun.security.rsa.SunRsaSign
security.provider.3=sun.security.ec.SunEC
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC
security.provider.10=apple.security.AppleProvider
JVM啟動時會將這些provider註冊進去,其實就是Security
初始化時會讀這個檔案。開發自定義的安全提供者,需要將類放到系統類路徑下。其實看看Provider類的程式碼,就知道Provider本質上是一個Properties檔案,裡面的kv儲存著引擎名和具體演算法類的實現。
可以通過下面的程式示例檢視具體的提供者引擎和演算法:
package com.taobao.cd.security;
import java.security.Provider;
import java.security.Security;
import java.util.Enumeration;
public class ProviderTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Provider[] providers = Security.getProviders();
for (int i = 0; i < providers.length; i++) {
System.out.println("" + (i + 1) + ":" + providers[i]);
for (Enumeration e = providers[i].keys(); e.hasMoreElements();) {
System.out.println(" " + e.nextElement());
}
}
}
}
其輸出如下,(擷取部分)
1:SUN version 1.8
Alg.Alias.Signature.SHA1/DSA
Alg.Alias.Signature.1.2.840.10040.4.3
Alg.Alias.Signature.DSS
SecureRandom.SHA1PRNG ImplementedIn
KeyStore.JKS
Alg.Alias.MessageDigest.SHA-1
MessageDigest.SHA
...
引擎類的結構設計
值得一提的是引擎類的結構設計。如上所說,引擎類除了給業務開發人員提供介面,還有一個任務就是要為第三方提供者使用。引擎為提供者提供了一個介面——SPI(security provider interface)。
還是以MessageDigest為例(這是訊息摘要引擎)。MessageDigest繼承了MessageDigestSpi。MessageDigestSpi抽象類定義了訊息摘要引擎要做的事情。MessageDigest內部持有一個Delegate委託類,MessageDigest的核心方法就是getInstance()獲取類的例項,實現見下:
public static MessageDigest getInstance(String algorithm, String provider)
throws NoSuchAlgorithmException, NoSuchProviderException
{
if (provider == null || provider.length() == 0)
throw new IllegalArgumentException("missing provider");
Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider);
if (objs[0] instanceof MessageDigest) {
MessageDigest md = (MessageDigest)objs[0];
md.provider = (Provider)objs[1];
return md;
} else {
MessageDigest delegate =
new Delegate((MessageDigestSpi)objs[0], algorithm);
delegate.provider = (Provider)objs[1];
return delegate;
}
}
通過Security.getImpl()反射獲取到對應的provider和演算法實現類,並通過型別判斷和else委託邏輯保證返回一個MessageDigest例項。
再具體一點,以Sun security提供的MD5演算法實現為例。雖然MD5並沒有直接實現MessageDigestSpi,但MD5的父類DigestBase繼承了MessageDigestSpi。所以實際上還是滿足這個架構的設計。DigestBase做了訊息摘要通用的實現,留了三個abstract介面:
abstract void implCompress(byte[] arg0, int arg1);
abstract void implDigest(byte[] arg0, int arg1);
abstract void implReset();
這幾個程式碼在MD5中具體實現:(擷取部分)
void implDigest(byte[] arg0, int arg1) {
long arg2 = this.bytesProcessed << 3;
int arg4 = (int) this.bytesProcessed & 63;
int arg5 = arg4 < 56 ? 56 - arg4 : 120 - arg4;
this.engineUpdate(padding, 0, arg5);
ByteArrayAccess.i2bLittle4((int) arg2, this.buffer, 56);
ByteArrayAccess.i2bLittle4((int) (arg2 >>> 32), this.buffer, 60);
this.implCompress(this.buffer, 0);
ByteArrayAccess.i2bLittle(this.state, 0, arg0, arg1, 16);
}
最後補充一個類圖說明下類的結構:
相關文章
- 畫架構圖相關架構
- mysql 官方架構相關圖MySql架構
- 結構體相關結構體
- 擁抱零信任理念,重構安全體系架構架構
- 對話京東安全首席架構師:電商平臺構建安全防護體系關鍵點架構
- Java軟體架構師-25個關注點Java架構
- 關於軟體架構和業務架構的思考架構
- 【體系結構】與Checkpoint相關的問題解決思路
- 阿里珍藏版Java框架體系架構手寫文件,Java架構師指南下載阿里Java框架架構
- MySQL體系架構MySql架構
- Tomcat 體系架構Tomcat架構
- SQLite體系架構SQLite架構
- 軟體體系架構的認識架構
- spring框架中三層架構相關的註解Spring框架架構
- 關於cpu體系架構的一些有趣的故事分享架構
- 8張圖瞭解JAVA整體構架知識體系!Java
- java程式設計師進階架構師你必須掌握的架構知識體系Java程式設計師架構
- java與作業系統相關的操作Java作業系統
- 『網際網路架構』軟體架構-mybatis體系結構(14)架構MyBatis
- 郵件安全相關開源軟體的介紹
- 2_指令集、體系架構、微架構架構
- interrupt結構體和相關函式結構體函式
- Java 集合(1)之 總體架構Java架構
- GPU體系架構(二):GPU儲存體系GPU架構
- C++系統相關操作4 - 獲取CPU(指令集)架構型別C++架構型別
- java中serverlet的體系結構JavaServer
- 構建相關
- 當零信任和雲安全組起CP,如何架構來強防護安全體系?架構
- Java Bean相關JavaBean
- Java架構師面試題全集:Java基礎+技術框架+系統架構+分散式系統Java架構面試題框架分散式
- 軟體體系架構課堂測試07 –邏輯架構設計架構
- 架構知識體系總結架構
- 淺談Android os體系架構Android架構
- Kafka體系架構、命令、Go案例Kafka架構Go
- 【ARM架構】armv8 系統安全概述架構
- 分散式系統的那些事兒 - SOA架構體系分散式架構
- java打包相關的步驟Java
- java架構的程式碼結構Java架構
- Java進階專題(二十) 訊息中介軟體架構體系(2)-- RabbitMQ研究Java架構MQ