SafeNet安装
1.文件准备
1、下载压缩包
2、在解压目录\SafeNet\PTK_SDK_Installer\Win64\Win64中顺序安装如下的安装包
3、安装结束后在“C:\Program Files\SafeNet\Protect Toolkit 5\Protect Toolkit C SDK\bin”目录中修改“gCTAdmin HSM.bat”,“gCTAdmin SW.bat”,“KMU
HSM.bat”和“KMU SW.bat”。这里确保修改start 命令为调用1.8版本的javaw.exe
例如:
start javaw.exe classpath kmu.jar;gctadmin.jar jprov.tools.admin.CtAdmin
2.创建Token
1、使用超级管理员权限打开CMD,进入此目录,运行gCTAdmin SW.bat,如下
在Security Office PIN中填写 admin,在USER PIN中填写 user,点击“OK”按钮
2、在出现的界面中选择user,密码是user
点击"OK"按钮
3、界面的顶部菜单选择“Edit”“Token”
4、在界面中选择“<slot 0>: (uninitialized slot)”,并点击“Initialize”按钮。
5、在出现的界面中写入token lable,Security Office PIN是admin,User PIN是user。点击“OK”按钮。
3.管理KeySet
1. 用超级管理员权限打开CMD,进入安装目录,运行“KMU SW.bat”,界面如下
在界面中选择“select a token”并选中“MyToken”
2、 在弹出的对话框中填入user的PIN user
3、可以看到目前MyToken中的keyset为空
4.传入KeySet到制定的Token
1、用超级管理员打开CMD,找到 C:\Program Files\SafeNet\Protect Toolkit 5\Protect Toolkit J RT\bin,运行“jprovdemo.bat”
2、选择SafeNet HSM,password输入user,点击“login”按钮,登录之后点击”keyEnter“ 填写对应信息
3、重新进入KMU SW.bat,则会看到录入的密钥,也可以直接创建密钥
Java-SafeNet集成
1.引入依赖
<dependency>
<groupId>au.com.safenet</groupId>
<artifactId>jprov_sfnt</artifactId>
<version>1.1.1.8</version>
</dependency>
2.加密实现
public interface KmsService {
/**
* ECB模式加密数据
*
* @param keyLabel
* @param data
* @return
*/
byte[] ecbEncrypte(String keyLabel, byte[] data);
/**
* 使用密钥和指定的方法加密
*
* @param keySpec
* @param transformation
* @param plain
* @param algorithmParameterSpecHex
* @return
*/
byte[] encrypt(KeySpec keySpec, String transformation, byte[] plain, String algorithmParameterSpecHex);
}
@Service
@Slf4j
@Profile(PearlLiteProfiles.PROFILE_KMS_SAFE_NET)
public class SafeNetKmsService implements InitializingBean, KmsService {
@Autowired
private PearlLiteSystemConfig config;
private Provider provider;
private KeyStore keyStore;
public SafeNetKmsService(PearlLiteSystemConfig config) {
this.config = config;
}
public static final String TRANSFORM_MOD_CBC = "CBC";
public static final String TRANSFORM_MOD_GCM = "GCM";
public static final int GCM_TAG_LENGTH = 16;
public static final String DESEDE_ECB_NOPADDING = "DESede/ECB/NoPadding";
@Override
public byte[] ecbEncrypte(String keyLabel, byte[] data) {
try {
Cipher cipher = getProvider() == null ? Cipher.getInstance(DESEDE_ECB_NOPADDING) : Cipher.getInstance(DESEDE_ECB_NOPADDING, getProvider());
Key key = getKey(new KeySpecContainer(keyLabel), DESEDE_ECB_NOPADDING);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] rt = cipher.doFinal(data);
return rt;
} catch (Exception e) {
throw new TerminalBaseException(TerminalException.SYSTEM_ERROR, e);
}
}
@Override
@SneakyThrows
public byte[] encrypt(KeySpec keySpec, String transformation, byte[] plain, String algorithmParameterSpecHex) {
Cipher cipher = getProvider() == null ? Cipher.getInstance(transformation) : Cipher.getInstance(transformation, getProvider());
Key key = getKey(keySpec, transformation);
AlgorithmParameterSpec spec = getAlgorithmParameters(transformation, algorithmParameterSpecHex);
if (spec != null) {
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
} else {
cipher.init(Cipher.ENCRYPT_MODE, key);
}
byte[] rt = cipher.doFinal(plain);
if (log.isDebugEnabled()) {
log.debug("Result of encrypt [{}] with key [{}] is [{}]", Hex.encodeHexString(plain), keySpec, Hex.encodeHexString(rt));
}
return rt;
}
protected AlgorithmParameterSpec getAlgorithmParameters(String transformation, String algorithmParameterSpecHex) throws DecoderException {
// CBC模式的有IV
if (transformation.toUpperCase().contains(TRANSFORM_MOD_CBC)) {
if (StringUtils.isNotBlank(algorithmParameterSpecHex)) {
return new IvParameterSpec(Hex.decodeHex(algorithmParameterSpecHex));
} else {
log.debug("No algorithmParameter, return default IV");
return new IvParameterSpec(new byte[16]);
}
}
//GCM
if (transformation.toUpperCase().contains(TRANSFORM_MOD_GCM)) {
if (StringUtils.isNotBlank(algorithmParameterSpecHex)) {
return new GCMParameterSpec(GCM_TAG_LENGTH * 8, Hex.decodeHex(algorithmParameterSpecHex));
} else {
log.debug("No algorithmParameter, return default IV");
return new GCMParameterSpec(GCM_TAG_LENGTH * 8, new byte[16]);
}
}
return null;
}
/**
* 获取provider
*
* @return 如果指定了provider,返回具体的provider,否则返回null
*/
protected Provider getProvider() {
return provider;
}
/**
* 获取对称密钥
*
* @param keySpec
* @param transformation
* @return
*/
public Key getKey(KeySpec keySpec, String transformation) throws Exception {
if (keySpec instanceof DerivedKeySpec && ((DerivedKeySpec) keySpec).getMasterKey() != null) {
DerivedKeySpec derivedKeySpec = ((DerivedKeySpec) keySpec);
byte[] intermediate = getDerivedKeySpecContent(derivedKeySpec);
log.debug("Key value of derivedKey [{}] is [{}]", derivedKeySpec, Hex.encodeHexString(intermediate));
// 手工组装中间密钥。
return JceKeyUtils.createKey(intermediate, transformation);
} else {
Key rt = getKeyInternal(keySpec, transformation);
if (rt == null) {
throw new TerminalBaseException(TerminalException.KEY_NOT_FOUND, keySpec);
} else {
log.debug("Get internal key [{}] for keySpec [{}]", rt, keySpec);
return rt;
}
}
}
/**
* safeNet 连接
*
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
String clzName = "au.com.safenet.crypto.provider.slot" + config.getSlot() + ".SAFENETProvider";
provider = (Provider) Class.forName(clzName).newInstance();
keyStore = KeyStore.getInstance("CRYPTOKI", provider);
keyStore.load(null, config.getSafeNetPassWord().toCharArray());
}
/**
* 获取分散密钥的具体值
*
* @param derivedKeySpec
* @return
* @throws Exception
*/
protected byte[] getDerivedKeySpecContent(DerivedKeySpec derivedKeySpec) throws Exception {
KeyDerivation derivation = derivedKeySpec.getKeyDerivation();
byte[] data = Hex.decodeHex(derivation.getDerivationDataHex());
return encrypt(derivedKeySpec.getMasterKey(), derivation.getAlgorithm(), data, null);
}
protected Key getKeyInternal(KeySpec keySpec, String transformation) throws Exception {
if (keySpec instanceof KeyLabelSpec) {
return keyStore.getKey(((KeyLabelSpec) keySpec).getKeyLabel(), config.getSafeNetPassWord().toCharArray());
}
throw new TerminalBaseException(TerminalException.KEY_SPEC_NOT_SUPPORT);
}
}
系统启用safeNet
spring:
profiles:
#加密方式配置
active: safeNet
综上所诉即为系统集成完成,调用加密方法即可