本文中含有需要您注意的重要提示信息,忽略該信息可能對您的業(yè)務造成影響,請務必仔細閱讀。
通過加密服務,您能對應用服務的數據進行可靠的加解密運算,實現數據保護,同時滿足數據安全方面的監(jiān)管合規(guī)要求。本文介紹如何通過加密服務實現應用服務數據的加解密。
背景信息
下圖為在應用系統(tǒng)中實現敏感數據加密和解密的典型部署方案。
數據加密流程
通過加密服務產生加密密鑰。
使用加密密鑰對應用服務數據的明文進行加密,產生應用數據密文,并將應用數據密文返回給應用服務。
應用服務把密文數據存儲到數據庫。
數據解密流程
應用系統(tǒng)從數據庫讀取已加密的密文數據,并將應用數據密文透傳給云密碼機進行解密。
密文解密后云密碼機將明文信息返回給應用系統(tǒng)。
密碼機提供密鑰生成和管理、數據加密和解密功能。整個密碼算法運算過程都在云密碼機中完成,數據通過密碼機處理后把密文數據存儲在數據庫中,提高了系統(tǒng)的安全性。下圖為敏感數據加密的時序圖。
資源準備
開始配置前,您需要準備以下資源:
數據庫:用于對應用數據密文進行安全存儲和讀取。
應用服務器:用于部署用戶的業(yè)務系統(tǒng),支持如下系統(tǒng)。
64位Linux系統(tǒng)
32位或64位Windows系統(tǒng)
EVSM:TASS EVSM,用于提供加密和解密等密碼服務。
步驟一:配置密碼機客戶端
如果您的業(yè)務需要正式上線,在購買加密服務實例后,您需要配置密碼機客戶端。
登錄加密服務管理控制臺,在頂部菜單欄,選擇目標地域。
下載并安裝密碼機實例管理工具。
在實例列表頁面,找到目標密碼機實例。
單擊規(guī)格列的金融數據密碼機,然后單擊下載密碼機實例管理工具。
解壓獲取到的密碼機實例管理工具,選擇以下任一方式安裝密碼機實例管理工具。
在本地終端安裝密碼機客戶端管理工具:安裝后需要通過VPN或物理專線使本地終端連接到密碼機實例所屬的VPC網絡。
在Windows操作系統(tǒng)的ECS實例上安裝密碼機客戶端管理工具:安裝后需要通過本地終端遠程登錄ECS實例,在ECS實例上操作密碼機實例管理工具。購買ECS實例的具體操作,請參見自定義購買實例。
使用密碼機實例管理工具初始化密碼機實例。
登錄密碼機實例管理工具。具體操作,請參見密碼機實例管理工具用戶使用手冊的《登錄》章節(jié)。
初始化密碼機實例。具體操作,請參見密碼機實例管理工具用戶使用手冊的《出廠初始化》或《快速初始化》章節(jié)。
步驟二:初始化SDK
使用以下方法初始化SDK。
hsm=hsmGeneralFinance.getInstance("./cacipher.ini");
步驟三:調用Java接口生成密鑰
您也可以通過密碼機管理工具產生隨機密鑰。具體操作,請從解壓后的密碼機管理工具軟件包中獲取管理工具的用戶使用手冊,參考用戶使用手冊中的《對稱密鑰管理》章節(jié)。
調用以下Java接口生成工作密鑰。
hsm.genWorkKey(keyType,algFlag,keyIndex,keyLable);
接口定義
public String[] genWorkKey(String keyType,
char keyFlag,
int storeKeyIndex,
String storeKeyLabel)
throws cn.tass.exceptions.TAException
請求參數
參數名稱 | 參數類型 | 參數描述 |
keyType | String | 密鑰類型。支持密鑰類型編碼和密鑰類型名稱兩種格式。例如:ZEK/DEK可以傳"00A"和"ZEK/DEK"兩種格式。取值:
|
algFlag | char | 在LMK下加密的密鑰密文標識。取值:
|
KeyIndex | int | 密鑰存儲索引。取值范圍:1~2048。 |
KeyLabel | String | 密鑰存儲標簽。包含0~16個ASII字符。 說明 在云密碼機內部存儲密鑰時標記密鑰的標簽說明。 |
請求示例
keyType:00A
algFlag:R
keyIndex:1
KeyLabel:test
返回值
0號索引:密鑰在LMK下加密的密文。
1號索引:密鑰校驗值。
拋出異常
cn.tass.exceptions.TAException //接口自定義異常。
步驟四:配置Java接口
您可以通過文件形式或者內容形式配置Java接口。
文件形式:支持直接將配置文件絕對路徑傳入初始化接口內。示例:
[LOGGER] logsw=error logPath=./ [HOST1] hsmModel=SJJ1310 linkNum=-5 host=192.168.19.19 port=8018 timeout=5 ifHeart=yes
文件格式要求:
分類
要求
示例
注釋
注釋行以符號“#”起始,不支持行內注釋。
#內容形式中的屬性字段與文件形式中的屬性字段保持一致。
配置域
配置域以方括號“[”和“]”標識。
說明配置域與鍵名不區(qū)分大小寫,為了便于區(qū)分建議配置域使用大寫。
[LOGGER]
配置項
配置項格式:“鍵名(Key)=鍵值(Value)”。
linkNum=-5
配置內容
支持使用空白字符(空格或制表符)等對內容進行對齊操作。
說明您可以在接口內拼裝字符串傳遞配置。
使用“{”和“}”,表示包括所有內容;使用“;”,表示換行。
無
Java接口中配置文件的基本屬性配置域包括日志屬性、EVSM屬性和應用屬性等,日志屬性和EVSM屬性的屬性字段說明請參見下表。
屬性分類
配置域
屬性字段
屬性字段說明
日志屬性
[LOGGER]
logsw
設置日志類別的開關,每種日志通過獨立的關鍵字開啟。取值:
error:錯誤日志
debug:調試日志
logPath
設置日志文件的保存目錄。
說明您需確保配置文件的目錄已經存在,且應用系統(tǒng)具有寫入權限。
EVSM屬性
[HOSTn]
說明n為該EVSM在當前配置文件中從1開始的序號,Java接口會按順序讀取多個EVSM的屬性,直到最后1個序號。
hsmModel
VSM類型標識,用于指定EVSM驅動。默認值SJJ1310。
linkNum
與云密碼機建立長連接的數量。默認值-10。
說明數字前的負號(-)表示僅使用連接池,如果數字前沒有負號表示優(yōu)先使用連接池。優(yōu)先使用連接池時,業(yè)務并發(fā)過高則Java接口中可能會創(chuàng)建短連接處理業(yè)務,對系統(tǒng)資源造成較大的影響。
host
EVSM主機服務IP地址,支持設置成域名形式。
port
EVSM主機服務端口。
timeout
超時時間。單位為秒,默認值6秒。
connTimeout
指定Java接口與逃生服務器建立網絡連接的超時時間。該屬性字段不存在時,使用timeout的取值。
readTimeout
指定Java接口從逃生服務器讀取信息的超時時間。該屬性字段不存在時,使用timeout的取值。
socketProtocol
通訊協議,支持TLSv1.2等版本協議。默認值TCP。
ifHeart
SDK對服務端的心跳探測,默認開啟。
內容形式:支持直接將配置信息以字符串的形式傳入初始化接口內。示例:
//內容形式中的屬性字段與文件形式中的屬性字段保持一致。 Stringconfig= "{" +"[LOGGER];" +"logsw=error;logPath=./;" +"[HOST1];" +"hsmModel=SJJ1310;" +"host=192.168.19.19;" +"port=8018;" +"connTimeout=5;" +"}";
步驟五:調用Java接口進行數據加解密
主要介紹了通過調用Java接口生成工作密鑰和進行通用數據加解密的操作方法。
數據加密
調用以下Java接口進行數據加密。
hsm.generalDataEnc(algType,keyType,sm4SymmKey,disperFactor,sessionType,sessionFactor,padFlag,inData,IV);
接口定義
public byte[] generalDataEnc(int algType,
String keyType,
Object key,
String disperFactor,
Int sessionType,
String sessionFactor,
Int padFlag,
byte[] inData,
String IV)
throws cn.tass.exceptions.TAException
請求參數
參數名稱 | 參數類型 | 參數描述 |
algType | int | 加密算法模式。取值:
|
keyType | String | 加密數據的源密鑰類型,支持密鑰類型名稱和密鑰類型編碼兩種格式。例如:ZEK/DEK可以傳"00A"和"ZEK/DEK"兩種格式。取值:
|
key | Object | 加密數據密鑰的索引或密文。
|
disperFactor | String | 密鑰分散因子的n級分散因子進行串聯,且每級分散因子必須為16個字節(jié)。 說明 針對敏感數據加密場景該參數取值為空字符串或NULL。 |
sessionType | int | 會話密鑰產生模式。
說明 針對敏感數據加密場景該參數取值為空字符串或NULL。 |
sessionFactor | String | 會話密鑰因子。
說明 針對敏感數據加密場景該參數取值為空字符串或NULL。 |
padFlag | int | PAD填充標識。取值:
說明 針對敏感數據加密場景該參數取值為1。 |
inData | byte[] | 輸入的明文數據。 說明 您可以根據應用業(yè)務自行輸入數據內容。 |
IV | String | 初始向量。僅當algType取值為1、2、3、4時支持該參數。
說明 ECB加密算法模式不需要IV,該參數取值為空字符串或NULL。 |
請求示例
algType:1
keyType:"00A"
key:symmKey[0] //加密的對稱密鑰密文,使用EVSM內部的索引密鑰,使用內部密鑰時為int類型。
disperFactor:null
sessionType:0
sessionFactor:null
padFlag:1
inData:根據用戶業(yè)務自行輸入數據內容。
IV:"00000000000000000000000000000000"
返回值
加密之后的密文數據。
拋出異常
cn.tass.exceptions.TAException //接口自定義異常。
數據解密
調用以下Java接口進行數據解密。
hsm.generalDataDec(algType,keyType,sm4SymmKey,disperFactor,sessionType,sessionFactor,padFlag,symmEnc,IV);
接口定義
public byte[] generalDataDec(int algType,
String keyType,
Object key,
String disperFactor,
int sessionType,
String sessionFactor,
int padFlag,
byte[] inData,
String IV)
throws cn.tass.exceptions.TAException
請求參數
參數名稱 | 參數類型 | 參數描述 |
algType | int | 加密算法模式。取值:
|
keyType | String | 加密數據的源密鑰類型,支持密鑰類型名稱和密鑰類型編碼兩種格式。例如:ZEK/DEK可以傳"00A"和"ZEK/DEK"兩種格式。取值:
|
key | Object | 加密數據密鑰的索引或密文。
|
disperFactor | String | 密鑰分散因子的n級分散因子進行串聯,且每級分散因子必須為16個字節(jié)。 說明 針對敏感數據加密場景該參數取值為空字符串或NULL。 |
sessionType | int | 會話密鑰產生模式。
說明 針對敏感數據加密場景該參數取值為空字符串或NULL。 |
sessionFactor | String | 會話密鑰因子。
說明 針對敏感數據加密場景該參數取值為空字符串或NULL。 |
padFlag | int | PAD填充標識。取值:
說明 針對敏感數據加密場景該參數取值為1。 |
inData | byte[] | 輸入的明文數據。 說明 您可以根據應用業(yè)務自行輸入數據內容。 |
IV | String | 初始向量。僅當algType取值為1、2、3、4時支持該參數。
說明 ECB加密算法模式不需要IV,該參數取值為空字符串或NULL。 |
請求示例
algType:1
keyType:"00A"
key:symmKey[0] //加密的對稱密鑰密文,使用EVSM內部的索引密鑰,使用內部密鑰時為int類型。
disperFactor:null
sessionType:0
sessionFactor:null
padFlag:1
inData:自行輸入加密后的數據。
IV:"00000000000000000000000000000000"
返回值
解密后的數據。
拋出異常
cn.tass.exceptions.TAException //程序運行異常。
示例
public class SensitiveDataEnc {
public static void main(String[] args) throws TAException {
// 接口初始化,采用配置文件的方式。
hsmGeneralFinance hsm = hsmGeneralFinance.getInstance("./cacipher.ini");
// 接口初始化2,采用配置內容的方式。
// String config =
// "{"
// + "[LOGGER];"
// + "logsw=error;logPath=./;"
// + "[HOST1];"
// + "hsmModel=SJJ1310;"
// + "host=192.168.19.19;"
// + "port=8018;"
// + "connTimeout=5;"
// + "}";
//
// hsmGeneralFinance hsm = hsmGeneralFinance.getInstance(config);
// 測試1產生隨機密鑰keyIndex為可變參數。
// 當該密鑰索引值取值為0時,表示不需要加密機保存生成的該條隨機對稱密鑰。
// 當keyIndex取值為1~2048時,表示將對稱密鑰儲存在加密機中,且執(zhí)行覆蓋操作(相同索引執(zhí)行覆蓋操作)。
int keyIndex = 0;
switch (keyIndex) {
case 0:
// 產生隨機SM4算法對稱密鑰。
String keyType = "00A";
char algFlag = 'R';
String keyLable = "sm4Key";
// 調用產生隨機密鑰接口。
String[] symmKey = hsm.genWorkKey(keyType, algFlag, keyIndex, keyLable);
System.out.println("對稱密鑰lmk下的密文值:" + symmKey[0]);
System.out.println("對稱密鑰校驗值:" + symmKey[1]);
// 測試2。
String str = "要加密的數據";
// CBC模式。
int algType = 1;
// 密鑰類型固定。
keyType = "00A";
// 執(zhí)行加密的對稱密鑰密文。
String sm4SymmKey = symmKey[0];
// 也可以使用加密機內部的索引密鑰,使用內部密鑰時為int類型。
String disperFactor = null;
int sessionType = 0;
String sessionFactor = null;
// 遵循強制80填充。
int padFlag = 1;
byte[] inData = str.getBytes();
String IV = "00000000000000000000000000000000";
// 調用數據加密接口。
byte[] symmEnc = hsm.generalDataEnc(algType, keyType, sm4SymmKey, disperFactor, sessionType, sessionFactor,
padFlag, inData, IV);
System.out.println("16進制字符串輸出對稱加密結果:" + Forms.byteToHexString(symmEnc)
+ ",如果進行解密,可使用接口功能函數'Forms.hexStringToByte()'將16進制字符串轉換為byte[]參與解密。");
// 調用數據解密接口。
byte[] symmDec = hsm.generalDataDec(algType, keyType, sm4SymmKey, disperFactor, sessionType, sessionFactor,
padFlag, symmEnc, IV);
System.out.println("解密結果與加密數據比較結果:" + Arrays.equals(symmDec, inData));
System.out.println("還原解密結果,通過字符集還原原文:" + new String(symmDec));
break;
// 此時生成對稱密鑰到1號索引位置,若已經存在,會執(zhí)行覆蓋操作。
case 1:
str = "要加密的數據";
// CBC模式。
algType = 1;
// 密鑰類型固定。
keyType = "00A";
// 執(zhí)行加密的對稱密鑰密文,使用加密機內部的索引密鑰,使用內部密鑰時為int類型。
int sm4SymmKeyIndex = 1;
disperFactor = null;
sessionType = 0;
sessionFactor = null;
// 遵循強制80填充。
padFlag = 1;
inData = str.getBytes();
IV = "00000000000000000000000000000000";
// 調用數據加密接口。
symmEnc = hsm.generalDataEnc(algType, keyType, sm4SymmKeyIndex, disperFactor, sessionType, sessionFactor,
padFlag, inData, IV);
System.out.println("16進制字符串輸出對稱加密結果:" + Forms.byteToHexString(symmEnc)
+ ",如果進行解密,可使用接口功能函數'Forms.hexStringToByte()'將16進制字符串轉換為byte[]參與解密。");
// 調用數據解密接口。
symmDec = hsm.generalDataDec(algType, keyType, sm4SymmKeyIndex, disperFactor, sessionType, sessionFactor,
padFlag, symmEnc, IV);
System.out.println("解密結果與加密數據比較結果:" + Arrays.equals(symmDec, inData));
System.out.println("還原解密結果,通過字符集還原原文:" + new String(symmDec));
break;
default:
break;
}
}
}
步驟六:同步應用系統(tǒng)密鑰
在部署密碼機實例時,您需要同步應用系統(tǒng)的密鑰和配置Java接口。應用密鑰存儲在密碼機實例內部和外部系統(tǒng)的同步方式不同。
密鑰存儲在密碼機實例內部系統(tǒng)
您需要根據密鑰索引將應用密鑰備份導出,然后通過密鑰恢復導入功能將備份密鑰導入到其他密碼機實例中,完成密鑰同步操作。以下內容以從A密碼機實例導出應用密鑰,并導入到B密碼機實例為例。
應用密鑰由隨機產生的備份密鑰加密,您可以將加密后的密文以文件的形式導出或存儲在UKEY中。同步密鑰時,您需要將UKEY插入需要同步的設備中同步密鑰。
備份導出A密碼機實例的應用密鑰。
打開密碼機實例管理工具,通過A密碼機實例的IP地址登錄VSM管理系統(tǒng)。
具體操作,請參見密碼機實例管理工具用戶使用手冊的《登錄》章節(jié)。
在頂部菜單欄,單擊密鑰管理頁簽,然后單擊備份導出。
在選擇導出密鑰類型和索引對話框,根據實際需要選擇密鑰類型并輸入密鑰索引,然后單擊確認。
您可以選擇將密鑰備份保存到文件或保存到UKEY內。本文以將密鑰備份保存到文件為例進行描述。
按照系統(tǒng)提示依次插入3個空UKEY并輸入口令,單擊下一步。
說明密碼機實例將依次制作出3個密鑰備份密鑰KBK UKEY。建議3個KBK UKEY由3個密鑰管理員分別保管。
選擇要保存密鑰密文的文件,單擊下一步。
EVSM將導出全部應用密鑰并保存到您選擇的文件中。
說明密鑰備份完成后,請您妥善保管3個KBK UKEY和密鑰備份文件,待密鑰恢復時使用。
將導出的應用密鑰導入到B密碼機實例進行恢復。
打開密碼機實例管理工具,通過B密碼機實例的IP地址登錄VSM管理系統(tǒng)。
具體操作,請參見密碼機實例管理工具用戶使用手冊的《登錄》章節(jié)。
在頂部菜單欄,單擊密鑰管理頁簽,然后選擇 。
說明恢復密鑰時使用任意2個密鑰備份UKEY即可還原出原始的KBK文件,然后將密鑰恢復到其他密碼機實例內部或者同步到熱備份的其他密碼機實例內部。
按照系統(tǒng)提示依次插入任意2個KBK UKEY并輸入口令,單擊下一步。
選擇要讀取的密鑰備份文件,等待系統(tǒng)完成應用密鑰的恢復,單擊完成。
密鑰存儲在密碼機實例外部系統(tǒng)
當應用密鑰經過本地主密鑰LMK(Local Master Key)分組加密保護后存儲在外部系統(tǒng),如果需要同步應用系統(tǒng)密鑰,您還需要同步密碼機實例的域名主密鑰DMK(Domain Master Key)。您可以通過密碼機實例的原始初始化,來產生DMK成分的UKEY。
當多個密碼機實例進行密鑰備份時,只需要在第一個密碼機實例上完成原始初始化后,對其他密碼機實例恢復初始化,即可完成多個密碼機實例的密鑰同步。以下內容以在A密碼機實例進行原始初始化,并在B密碼機實例恢復初始化為例。
在A密碼機實例上進行原始初始化。
警告原始初始化將清空密碼機實例內的所有密鑰,如果您希望保存密碼機中的數據,請使用UKEY備份。備份的具體操作請參見密碼機實例管理工具的用戶使用手冊。
打開密碼機實例管理工具,通過A密碼機實例的IP地址登錄VSM管理系統(tǒng)。
具體操作,請參見密碼機實例管理工具用戶使用手冊的《登錄》章節(jié)。
在頂部菜單欄,單擊密鑰管理頁簽,然后單擊原始初始化。
在彈出的警示提示框,單擊下一步。
根據系統(tǒng)提示,制作至少2個域名主密鑰DMK成份的UKEY。
建議您采用3選2授權控制機制并制作3個授權UKEY。
說明具體操作,請參見密碼機實例管理工具用戶管理手冊的《原始初始化》章節(jié)。
對B密碼機實例進行恢復初始化(即導入DMK)。
警告恢復初始化將清空密碼機實例內的所有密鑰,如果您希望保存密碼機中的數據,請使用UKEY備份。備份的具體操作請參見密碼機實例管理工具的用戶使用手冊。
打開密碼機實例管理工具,通過B密碼機實例的IP地址登錄VSM管理系統(tǒng)。
具體操作,請參見密碼機實例管理工具用戶使用手冊的《登錄》章節(jié)。
在頂部菜單欄,單擊密鑰管理頁簽,然后單擊恢復初始化。
在彈出的警示提示框,單擊下一步。
在恢復初始化-第一步對話框,輸入DMK成份UKEY數目,單擊下一步。
在恢復初始化-第二步對話框,依次插入n個成份UKEY并輸入UKEY口令,單擊導入成份UKEY,密碼機實例將讀取UKEY內的DMK成份數據。
DMK成份導入完成后,單擊合成DMK。
DMK合成成功后,確定授權機制。
如果您的其他密碼機實例共用一套授權UKEY,請選擇同步授權信息。您只需插入有效授權的UKEY并輸入口令,單擊完成,完成恢復初始化。
如果您的每個密碼機實例都需要使用獨立的授權UKEY,選中制作新的授權UKEY,并從選擇授權機制列表中選擇請選擇1選1授權控制機制,制作授權UKEY完成恢復初始化。
在頂部菜單欄,單擊密鑰管理頁簽,然后單擊獲取DMK校驗值。
當DMK同步到多個密碼機實例時,可以通過比對多個密碼機實例的DMK校驗值來確定同步后的DMK是否一致。
在密鑰管理頁簽,單擊導出DMK成份。
您可以將DMK成份導出到多個UKEY中,在原有密碼機實例的成份UKEY丟失或損壞的情況下,能夠重新合成出與原有密碼機實例同樣的DMK成份。
重要導出DMK成份時,不能保證DMK成份UKEY中的密鑰備份與原有密碼機實例的成份UKEY中的密鑰備份完全相同。