密码机实例是密码机的硬件加密模块虚拟化形成的资源,具备对数据的加解密运算能力,可以实现加密服务的所有功能。本文介绍如何使用密码机实例。

前提条件

您已经创建专有网络VPC(Virtual Private Cloud)。具体操作,请参见创建专有网络

步骤一:创建密码机实例

  1. 登录加密服务管理控制台,在顶部菜单栏,选择目标地域。
  2. 实例列表页面,单击创建密码机实例
  3. 在加密服务购买页面,参考下表配置信息,然后单击立即购买并完成支付。
    配置项 说明
    区域

    选择开通加密服务的地域,包括华南1(深圳)华北2(北京)华东2(上海)华东1(杭州)

    加密服务只能在VPC中使用,且加密服务的地域必须与您的ECS及VPC的地域相同。

    可用区

    选择开通加密服务的可用区。建议您将密码机部署在不同的可用区,保障您的业务不会因可用区内某一机房发生事故而受影响。

    说明
    • 只有处于同一地域的可用区之间才能实现网络互通。
    • 加密服务和ECS实例可以在不同的可用区。
    密码机类型 选择设备型号,包括金融数据密码机EVSM通过服务器密码机GVSM签名验证服务器SVSM。关于密码机设备类型的更多信息,请参见功能特性
    购买数量 选择需要购买的密码机数量。如果您在生产环境中使用加密服务,为了保证加密服务的高可用性,建议您至少购买2个密码机实例。
    购买时长 选择购买的有效服务时间。

    为了防止加密服务到期未及时续费而导致的密钥永久性丢失,建议您购买时选择到期自动续费。当您选择到期自动续费后,阿里云会在服务到期前9个自然日从您购买密码机时使用的支付账户自动扣款,为了防止扣费失败,请确保您的支付账户余额充足。

    创建成功后,密码机实例将显示在实例列表页面,并且状态未启用

步骤二:启用并配置密码机实例

  1. 登录加密服务管理控制台,在顶部菜单栏,选择目标地域。
  2. 实例列表页面,找到创建后的密码机实例,在操作列单击启用
  3. 密码机实例配置对话框,配置密码机实例,然后单击确定
    配置项 说明
    所属的VPC网络ID 选择密码机实例需要绑定的VPC。
    VPC子网 选择密码机实例所属的VPC子网IP。
    私网IP地址 为密码机实例分配一个所属的私网IP。
    注意
    • 您分配给密码机实例的私网IP地址必须是所属的VPC子网网段中的IP地址,否则配置将会失败。
    • 末位为253、254、255的IP地址为系统保留地址。当您使用系统保留地址的网络时,该密码机实例只能在局域网内部进行通信,不能与其他网络互连。为了不影响网络互通,在分配私网IP地址时,请不要分配系统保留地址。
    设置密码机实例白名单 设置访问该密码机实例的访问白名单,不在白名单内的访问请求将被拒绝。
    配置成功后,密码机实例的状态变为已启用

步骤三:配置密码机实例管理工具

您可以使用密码机实例管理工具来管理和配置密码机,包括密钥管理、配置服务器端口等。

注意 密码机实例管理工具仅支持安装在Windows操作系统。
  1. 登录加密服务管理控制台,在顶部菜单栏,选择目标地域。
  2. 下载并安装密码机实例管理工具。
    1. 实例列表页面,找到目标密码机实例。
    2. 单击密码机实例的规格列信息,然后单击下载密码机实例管理工具
      下载密码机实例管理工具
    3. 解压获取到的密码机软件包,选择以下任一方式安装密码机实例管理工具。
      • 在本地终端安装密码机客户端管理工具,然后通过VPN或物理专线使本地终端连接到密码机实例所属的VPC网络。
      • 在ECS实例上安装密码机客户端管理工具,然后通过本地终端远程登录ECS实例,在ECS实例上操作密码机实例管理工具。购买ECS实例的具体操作,请参见使用向导创建实例
  3. 登录密码机实例管理工具,配置服务端口属性。具体操作,请参见密码机实例管理工具用户管理手册的《登录》章节和《设备配置》章节。
    您可以在解压后的密码机软件包中获取密码机实例管理工具用户管理手册。

步骤四:使用密码机实例

您可以从步骤三:配置密码机实例管理工具获取到的密码机软件包中找到密码机的开发手册、SDK测试程序等。在完成密码机实例配置后,您可以参考开发手册,调用API接口使用密码机实例。

以GVSM为例,您可以使用其中的测试用例JceTestMain.java来测试密码机实例。代码示例如下:

注意 您需要将用例中的IP地址(121.41.XX.XX)修改为密码机实例分配的私网IP地址。
import cn.com.tass.jce.castle.hsm.connector.pool.PooledConfigReader;
import cn.com.tass.jce.castle.tc.encodings.Hex;
import javax.crypto.*;
import java.security.*;
import java.util.*;

public class APITest {

    public static void main(String[] args) throws Exception {
        //加载配置
        String config = "{"
                    + "[LOGGER];"
                    + "logsw=debug,error;"
                    + "logPath=./;"
                    + "[HOST 1];"
                    + "hsmModel=GHSM;"
                    + "host=121.41.XX.XX;"
                    + "linkNum=-3;"
                    + "port=9021;"
                    + "timeout=5;"
                    + "}";
        PooledConfigReader.setConfig(config);

        //产生随机数
        testGenRandom();
        //SM2签名 验签
        testOutKeySM2SignAndVeirfy();
        //对称密钥加解密数据
        testOutKeyAES128EncAndDec();
    }

    /**
     * 外部密钥AES128加解密
     */
    public static void testOutKeyAES128EncAndDec() {
        try {
            byte[] myAAD = Hex.decode("31313131313131313131313131313131");
            //产生密钥
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES", "TASS");
            keyGenerator.init(128);
            SecretKey key = keyGenerator.generateKey();
            byte[] iv = Hex.decode("31313131313131313131313131313131");
            byte[] plain = Hex.decode("31313131313131313131313131313131");
            //调用接口进行内部密钥加解密
            symEncAndDec("AES128 out key", key, "AES", plain, iv, myAAD);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * ECB、CBC 对称加密
     *
     * @param flag  标识
     * @param key   密钥
     * @param alg   算法名称
     * @param plain 待加密的数据
     * @param iv    IV值
     * @param add   GCM模式下的add值
     */
    private static void symEncAndDec(String flag, Key key, String alg, byte[] plain, byte[] iv, byte[] add) {
        try {
            //ECB/NoPadding
            Cipher encipher = Cipher.getInstance(alg + "/ECB/NoPadding", "TASS");
            Cipher decipher = Cipher.getInstance(alg + "/ECB/NoPadding", "TASS");
            encipher.init(Cipher.ENCRYPT_MODE, key);
            decipher.init(Cipher.DECRYPT_MODE, key);
            //加密
            byte[] resultEnc = encipher.doFinal(plain);

            //System.out.println("("+flag+")"+alg + "/ECB/NoPadding" + " enc result = " + new String(Hex.encode(resultEnc)));
            //解密
            byte[] resultDec = decipher.doFinal(resultEnc);
            //System.out.println("("+flag+")"+alg + "/ECB/NoPadding" + " dec result = " + new String(Hex.encode(resultDec)));
            if (!verifyResult(plain, resultDec)) {
                System.err.println("(" + flag + ")" + alg + "/ECB/NoPadding" + "解密失败");
                System.out.print("\n");
            } else {
                System.out.println("(" + flag + ")" + alg + "/ECB/NoPadding" + "解密成功");
                System.out.print("\n");
            }
            byte[] newPlain = Hex.decode("313131313131313131313131313131313233");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static boolean verifyResult(byte[] enc, byte[] dec) {
        return Arrays.equals(enc, dec);
    }

    /**
     * SM2外部密钥签名验签
     */
    public static void testOutKeySM2SignAndVeirfy() {
        try {
            //待签名的原文数据
            byte[] src = Hex.decode("313233");
            //使用KeyPairGenerator产生密钥对充当外部密钥
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("SM2", "TASS");
            keyPairGenerator.initialize(256);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();

            //开始签名
            Signature sign = Signature.getInstance("SM3withSM2", "TASS");
            sign.initSign(keyPair.getPrivate());
            sign.update(src);
            byte[] signResult = sign.sign();
            System.out.println("SM3withSM2 out key sign result = " + new String(Hex.encode(signResult)));

            //开始验签
            Signature verify = Signature.getInstance("SM3withSM2", "TASS");
            verify.initVerify(keyPair.getPublic());
            verify.update(src);
            boolean verifyResult = verify.verify(signResult);
            System.out.println("SM3withSM2 out key verify result = " + verifyResult);

            //计算摘要值
            MessageDigest digest = MessageDigest.getInstance("SM3", "TASS");
            byte[] digestData = digest.digest(src);
            //SM3withSM2ForHash开始签名
            sign = Signature.getInstance("SM3withSM2ForHash", "TASS");
            sign.initSign(keyPair.getPrivate());
            sign.update(digestData);
            signResult = sign.sign();
            System.out.println("SM3withSM2ForHash int key sign result = " + new String(Hex.encode(signResult)));

            //SM3withSM2ForHash开始验签
            verify = Signature.getInstance("SM3withSM2ForHash", "TASS");
            verify.initVerify(keyPair.getPublic());
            verify.update(digestData);
            verifyResult = verify.verify(signResult);
            System.out.println("SM3withSM2ForHash int key verify result = " + verifyResult);
            System.out.print("\n");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 产生随机数
     */
    public static void testGenRandom() {
        try {
            SecureRandom instance = SecureRandom.getInstance("HSM", "TASS");
            instance.nextInt();
            byte[] bytes = new byte[1024];
            instance.nextBytes(bytes);
            //输出随机数
            System.out.println("1024 random : " + new String(Hex.encode(bytes)));
            System.out.print("\n");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

更多操作

为密码机实例创建集群

您可以将处于不同的密码机实例加入到同一集群进行统一管理,为业务应用提供密码计算的高可用性、负载均衡以及横向扩展的能力。创建集群的具体操作,请参见使用密码机实例集群

修改密码机实例配置

密码机实例未加入集群时,您可以修改密码机实例所属的VPC、VPC子网、私网IP地址和密码机实例白名单;密码机实例加入集群后,您只能修改密码机实例的私网IP地址。

  1. 实例列表页面,找到目标密码机实例,在操作列选择更多 > 配置
  2. 密码机实例配置对话框,修改密码机实例的配置,然后单击确定

停用密码机实例

重置密码机实例或者从集群中删除密码机实例前,您需要先停用密码机实例的业务功能。

注意
  • 停用会断开密码机实例的网络连接,请谨慎操作。
  • 不允许停用集群中的主密码机实例。
  1. 实例列表页面,找到目标密码机实例,在操作列单击停用
  2. 在弹出的对话框,再次单击停用
    停用后,密码机实例的状态列显示为已停用

重置密码机实例

停用密码机实例后,您可以通过重置密码机实例,恢复密码机实例为出厂状态,即未初始化状态。

注意 重置将清空密码机实例中的数据,并恢复到出厂状态,请谨慎操作。
  1. 实例列表页面,找到目标密码机实例,在操作列单击重置
  2. 在弹出的对话框,再次单击重置

恢复密码机实例

通过恢复密码机实例,重新启用已被停用的密码机实例业务。

  1. 实例列表页面,找到目标密码机实例,在操作列单击恢复
  2. 在弹出的对话框,再次单击恢复
    恢复后,密码机实例的状态列显示为已启用