PKI - 非对称加密算法

密钥管理是对称加密算法系统不容忽视的问题,它成为安全系统中最为薄弱的环节。为了弥补这一弱势,非对称加密算法应运而生。

非对称加密算法源于DH算法(Diffie-Hellman,密钥交换算法),由W.Diffie和M.Hellman共同提出。该算法为非对称加密算法奠定了基础,堪称非对称加密算法之鼻祖。

DH算法提出后,国际上相继出现了各种实用性更强的非对称加密算法,其构成主要是基于数学问题的求解,主要分为两类:

  • 基于因子分解难题。RSA算法是最为典型的非对称加密算法,该算法由美国麻省理工学院(MIT)的Ron Rivest、Adi Shamir和Leonard Adleman三位学者提出,并以这三位学者的姓氏开头字母命名,称为RSA算法。RSA算法是当今应用范围最为广泛的非对称加密算法,也是第一个既能用于数据加密也能用于数字签名的算法。

  • 基于离散对数难题。ElGamal算法由TaherElGamal提出,以自己的名字命名。该算法既可用于加密/解密,也可用于数字签名,并为数字签名算法形成标准提供参考。美国的DSS(Digital Signature Standard,数据签名标准)的DSA(Digital Signature Algorithm,数字签名算法)经ElGamal算法演变而来。

ECC(Elliptical Curve Cryptography,椭圆曲线加密)算法以椭圆曲线理论为基础,在创建密钥时可做到更快、更小,并且更有效。ECC算法通过椭圆曲线方程式的性质产生密钥,而不是采用传统的方法利用大质数的积来产生。

1. 密钥交换算法(DH&ECDH)

1.1 DH

对称加密算法提高数据安全性的同时带来了密钥管理的复杂性。消息收发双方若想发送加密消息,必须事先约定好加密算法并发放密钥。而如何安全的传递密钥,成为对称加密算法的一个棘手问题。密钥交换算法(Diffie-Hellman算法,简称DH算法)成为解决这一问题的金钥匙!

(甲方)发送方 (乙方)接收方 1. 构建甲方密钥 2. 公布甲方公钥 3. 利用甲方公钥构建乙方密钥 4. 公布乙方公钥 5. 使用甲方私钥、乙方公钥构建本地密钥 6. 使用乙方私钥、甲方公钥构建本地密钥 7. 使用本地密钥对消息加密 8. 发送加密消息 9. 使用本地密钥对消息解密 (甲方)发送方 (乙方)接收方

代码实现

public static final String KEY_ALGORITHM = "DH";
public static final String SECRET_ALGORITHM = "AES";
public static final int KEY_SIZE = 512;
public static final String PUBLIC_KEY = "DHPublicKey";
public static final String PRIVATE_KEY = "DHPrivateKey";

/**
 * 生成甲方密钥对(含公钥、私钥)
 *
 * @return map
 * @throws Exception 异常
 */
public Map<String, Object> initKey() throws Exception {
    // 初始化密钥对生成器
    final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
    keyPairGenerator.initialize(KEY_SIZE);

    // 生成密钥对
    final KeyPair keyPair = keyPairGenerator.generateKeyPair();
    // 获取公钥
    final PublicKey publicKey = keyPair.getPublic();
    // 获取私钥
    final PrivateKey privateKey = keyPair.getPrivate();

    // 构造返回map
    Map<String, Object> keyMap = new HashMap<>();
    keyMap.put(PUBLIC_KEY, publicKey);
    keyMap.put(PRIVATE_KEY, privateKey);

    return keyMap;
}
/**
 * 根据甲方公钥生成乙方密钥对(含公钥、私钥)
 *
 * @param key 甲方公钥
 * @return map
 * @throws Exception 异常
 */
public Map<String, Object> initKey(byte[] key) throws Exception {
    // 解析甲方公钥
    final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key);
    // 实例化密钥工厂
    final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    // 产生甲方公钥
    final PublicKey aPublicKey = keyFactory.generatePublic(x509EncodedKeySpec);

    // 由甲方公钥构建乙方密钥
    final DHParameterSpec dhParameterSpec = ((DHPublicKey) aPublicKey).getParams();
    // 初始化密钥对生成器
    final KeyPairGenerator dh = KeyPairGenerator.getInstance(keyFactory.getAlgorithm());
    dh.initialize(dhParameterSpec);
    // 生成密钥对
    final KeyPair keyPair = dh.generateKeyPair();
    // 获取公钥
    final PublicKey publicKey = keyPair.getPublic();
    // 获取私钥
    final PrivateKey privateKey = keyPair.getPrivate();

    // 构造返回map
    Map<String, Object> keyMap = new HashMap<>();
    keyMap.put(PUBLIC_KEY, publicKey);
    keyMap.put(PRIVATE_KEY, privateKey);
    return keyMap;
}
/**
 * 生成密钥
 * @param publicKey 对方公钥
 * @param privateKey 自己私钥
 * @return 密钥
 * @throws Exception 异常
 */
public byte[] getSecretKey(byte[] publicKey, byte[] privateKey) throws Exception {
    // 初始化密钥工厂
    final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

    // 初始化公钥
    final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey);
    final PublicKey pubKey = keyFactory.generatePublic(x509EncodedKeySpec);

    // 初始化私钥
    final PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey);
    final PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

    // 实例化
    final KeyAgreement keyAgreement = KeyAgreement.getInstance(keyFactory.getAlgorithm());
    keyAgreement.init(priKey);
    keyAgreement.doPhase(pubKey, true);

    // 生成本地密钥
    final SecretKey secretKey = keyAgreement.generateSecret(SECRET_ALGORITHM);
    return secretKey.getEncoded();
}
/**
 * 取得公钥
 *
 * @param keyMap 密钥map
 * @return 公钥
 */
public byte[] getPublicKey(Map<String, Object> keyMap) {
    final Key key = (Key) keyMap.get(PUBLIC_KEY);
    return key.getEncoded();
}

/**
 * 取得私钥
 *
 * @param keyMap 密钥map
 * @return 私钥
 */
public byte[] getPrivateKey(Map<String, Object> keyMap) {
    final Key key = (Key) keyMap.get(PRIVATE_KEY);
    return key.getEncoded();
}
/**
 * 数据加密
 *
 * @param data 待加密数据
 * @param key  密钥
 * @return 加密后数据
 */
public byte[] encrypt(byte[] data, byte[] key) throws Exception {
    // 生成本地密钥
    final SecretKeySpec secretKeySpec = new SecretKeySpec(key, SECRET_ALGORITHM);
    // 数据加密
    final Cipher cipher = Cipher.getInstance(secretKeySpec.getAlgorithm());
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
    return cipher.doFinal(data);
}

/**
 * 数据解密
 *
 * @param data 待解密数据
 * @param key  密钥
 * @return 解密后数据
 */
public byte[] decrypt(byte[] data, byte[] key) throws Exception {
    // 生成本地密钥
    final SecretKeySpec secretKeySpec = new SecretKeySpec(key, SECRET_ALGORITHM);
    // 数据加密
    final Cipher cipher = Cipher.getInstance(secretKeySpec.getAlgorithm());
    cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
    return cipher.doFinal(data);
}

测试用例

@Test
public void testDH() throws Exception {
    final Map<String, Object> aKeyMap = initKey();
    final byte[] aPublicKey = getPublicKey(aKeyMap);
    final byte[] aPrivateKey = getPrivateKey(aKeyMap);
    System.out.println("甲方公钥:" + Base64.toBase64String(aPublicKey));
    System.out.println("甲方私钥:" + Base64.toBase64String(aPrivateKey));

    final Map<String, Object> bKeyMap = initKey(aPublicKey);
    final byte[] bPublicKey = getPublicKey(bKeyMap);
    final byte[] bPrivateKey = getPrivateKey(bKeyMap);
    System.out.println("乙方公钥:" + Base64.toBase64String(bPublicKey));
    System.out.println("乙方私钥:" + Base64.toBase64String(bPrivateKey));

    final byte[] aSecretKey = getSecretKey(bPublicKey, aPrivateKey);
    final byte[] bSecretKey = getSecretKey(aPublicKey, bPrivateKey);
    System.out.println("甲方密钥:" + Base64.toBase64String(aSecretKey));
    System.out.println("乙方密钥:" + Base64.toBase64String(bSecretKey));

    final byte[] aEncrypt = encrypt("我是阿汤哥".getBytes(), aSecretKey);
    final byte[] bDecrypt = decrypt(aEncrypt, bSecretKey);
    System.out.println("甲方加密消息:" + Base64.toBase64String(aEncrypt));
    System.out.println("乙方解密消息:" + Base64.toBase64String(bDecrypt));

    final byte[] bEncrypt = encrypt("Hello, 阿汤哥".getBytes(), bSecretKey);
    final byte[] aDecrypt = decrypt(bEncrypt, aSecretKey);
    System.out.println("乙方加密消息:" + Base64.toBase64String(bEncrypt));
    System.out.println("甲方解密消息:" + Base64.toBase64String(aDecrypt));
}

使用jdk8执行本用例时如果报错

java.security.NoSuchAlgorithmException: Unsupported secret key algorithm: AES

	at com.sun.crypto.provider.DHKeyAgreement.engineGenerateSecret(DHKeyAgreement.java:387)
	at javax.crypto.KeyAgreement.generateSecret(KeyAgreement.java:648)
	at com.jd.eps.eis.product.core.config.DHTest.getSecretKey(DHTest.java:110)
	at com.jd.eps.eis.product.core.config.DHTest.testDH(DHTest.java:183)

可以通过增加vm参数 -Djdk.crypto.KeyAgreement.legacyKDF=true 解决。

执行结果

甲方公钥:MIHgMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgANEAAJBAMCeFF4M4gFXNabyak7DplZnTVPJCNpw9eOao4BWNrdu8ptUiTg4kwmP8bxjot873vQ7QDg4cPyTFJGZ/c3HApE=
甲方私钥:MIHSAgEAMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgAQzAjEA1f2vYbDfzWpVlX8ib4ftWD5q24Mzh74C0L+ze8ienkfwv41dErOl0HqZOmmf18HN
乙方公钥:MIHgMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgANEAAJBAJ3BzkiX8n6RurBasjqLYwCbewwX0ZkWykCzyQj6y/4uBgNX0m+0bgPX1emxlFt/N3ueC8803OhNcprcHRxschY=
乙方私钥:MIHSAgEAMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgAQzAjEAqi55vmMEF5pfS4//fvfqELLlo817cCRlRMOZ+sQ9HLtroIJ16x7RWusDpK75dqxA
甲方密钥:sSVOKIBcVtQ5h806csVXzmkPZWUhC75Xp9glwAjFWhY=
乙方密钥:sSVOKIBcVtQ5h806csVXzmkPZWUhC75Xp9glwAjFWhY=
甲方加密消息:DPftIVbpAGj7dkF73QB4zw==
乙方解密消息:我是阿汤哥
乙方加密消息:FTZnyPN+ZAzdqU4vEKjkMCo6U0TLlKPDyL3zoBSGvvQ=
甲方解密消息:Hello, 阿汤哥

1.2 ECDH

JDK8没有ECDH的实现,需要添加Provider。

Security.addProvider(new BouncyCastleProvider());

根据甲方公钥生成乙方密钥对时需对ParameterSpec进行调整。

/**
 * 根据甲方公钥生成乙方密钥对(含公钥、私钥)
 *
 * @param key 甲方公钥
 * @return map
 * @throws Exception 异常
 */
public Map<String, Object> initKey(byte[] key) throws Exception {
    // 解析甲方公钥
    final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key);
    // 实例化密钥工厂
    final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    // 产生甲方公钥
    final PublicKey aPublicKey = keyFactory.generatePublic(x509EncodedKeySpec);

    // 由甲方公钥构建乙方密钥
    final ECParameterSpec ecParameterSpec = ((ECPublicKey) aPublicKey).getParams();
    // 初始化密钥对生成器
    final KeyPairGenerator dh = KeyPairGenerator.getInstance(keyFactory.getAlgorithm());
    dh.initialize(ecParameterSpec);
    // 生成密钥对
    final KeyPair keyPair = dh.generateKeyPair();
    // 获取公钥
    final PublicKey publicKey = keyPair.getPublic();
    // 获取私钥
    final PrivateKey privateKey = keyPair.getPrivate();

    // 构造返回map
    Map<String, Object> keyMap = new HashMap<>();
    keyMap.put(PUBLIC_KEY, publicKey);
    keyMap.put(PRIVATE_KEY, privateKey);
    return keyMap;
}

2. 典型非对称加密算法 - RSA

甲方(发送者) 乙方(接收者) 1. 构建密钥对 2. 发布公钥 3. 使用私钥加密数据 4. 发送加密数据 5. 使用甲方公钥解密数据 6. 使用甲方公钥加密数据 7. 发送加密数据 8. 使用私钥解密数据 甲方(发送者) 乙方(接收者)

代码实现

public static final String KEY_ALGORITHM = "RSA";
public static final int KEY_SIZE = 512;
public static final String PUBLIC_KEY = "DHPublicKey";
public static final String PRIVATE_KEY = "DHPrivateKey";

/**
 * 生成甲方密钥对(含公钥、私钥)
 *
 * @return map
 * @throws Exception 异常
 */
public Map<String, Object> initKey() throws Exception {
    // 初始化密钥对生成器
    final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
    keyPairGenerator.initialize(KEY_SIZE);

    // 生成密钥对
    final KeyPair keyPair = keyPairGenerator.generateKeyPair();
    // 获取公钥
    final PublicKey publicKey = keyPair.getPublic();
    // 获取私钥
    final PrivateKey privateKey = keyPair.getPrivate();

    // 构造返回map
    Map<String, Object> keyMap = new HashMap<>();
    keyMap.put(PUBLIC_KEY, publicKey);
    keyMap.put(PRIVATE_KEY, privateKey);

    return keyMap;
}

/**
 * 取得公钥
 *
 * @param keyMap 密钥map
 * @return 公钥
 */
public byte[] getPublicKey(Map<String, Object> keyMap) {
    final Key key = (Key) keyMap.get(PUBLIC_KEY);
    return key.getEncoded();
}

/**
 * 取得私钥
 *
 * @param keyMap 密钥map
 * @return 私钥
 */
public byte[] getPrivateKey(Map<String, Object> keyMap) {
    final Key key = (Key) keyMap.get(PRIVATE_KEY);
    return key.getEncoded();
}
/**
 * 使用私钥加密数据
 *
 * @param data       待加密数据
 * @param privateKey 私钥
 * @return 加密后数据
 */
public byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {
    // 获取私钥
    final PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey);
    final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    // 生成私钥
    final PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
    // 数据加密
    final Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    cipher.init(Cipher.ENCRYPT_MODE, priKey);
    return cipher.doFinal(data);
}

/**
 * 使用公钥解密数据
 *
 * @param data      待解密数据
 * @param publicKey 公钥
 * @return 解密后数据
 */
public byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
    // 获取公钥
    final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey);
    final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    // 生成公钥
    final PublicKey pubKey = keyFactory.generatePublic(x509EncodedKeySpec);
    // 数据加密
    final Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    cipher.init(Cipher.DECRYPT_MODE, pubKey);
    return cipher.doFinal(data);
}
/**
 * 使用公钥加密数据
 *
 * @param data      待解密数据
 * @param publicKey 公钥
 * @return 解密后数据
 */
public byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
    // 获取公钥
    final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey);
    final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    // 生成公钥
    final PublicKey pubKey = keyFactory.generatePublic(x509EncodedKeySpec);
    // 数据加密
    final Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    cipher.init(Cipher.ENCRYPT_MODE, pubKey);
    return cipher.doFinal(data);
}

/**
 * 使用私钥解密数据
 *
 * @param data       待加密数据
 * @param privateKey 私钥
 * @return 加密后数据
 */
public byte[] decryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {
    // 获取私钥
    final PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey);
    final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    // 生成私钥
    final PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
    // 数据加密
    final Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    cipher.init(Cipher.DECRYPT_MODE, priKey);
    return cipher.doFinal(data);
}
@Test
public void testRSA() throws Exception {
    Security.addProvider(new BouncyCastleProvider());

    final Map<String, Object> aKeyMap = initKey();
    final byte[] aPublicKey = getPublicKey(aKeyMap);
    final byte[] aPrivateKey = getPrivateKey(aKeyMap);
    System.out.println("甲方公钥:" + Base64.toBase64String(aPublicKey));
    System.out.println("甲方私钥:" + Base64.toBase64String(aPrivateKey));


    final byte[] aEncrypt = encryptByPrivateKey("我是阿汤哥".getBytes(), aPrivateKey);
    final byte[] bDecrypt = decryptByPublicKey(aEncrypt, aPublicKey);
    System.out.println("甲方:使用甲方私钥加密消息:" + Base64.toBase64String(aEncrypt));
    System.out.println("乙方:使用甲方公钥解密消息:" + new String(bDecrypt));

    final byte[] bEncrypt = encryptByPublicKey("Hello, 阿汤哥".getBytes(), aPublicKey);
    final byte[] aDecrypt = decryptByPrivateKey(bEncrypt, aPrivateKey);
    System.out.println("乙方:使用甲方公钥加密消息:" + Base64.toBase64String(bEncrypt));
    System.out.println("甲方:使用甲方私钥解密消息:" + new String(aDecrypt));
}

执行结果

甲方公钥:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ7vEoMQFnSZq8tIKydTxeZQZbg3EzZ+uoqMB6xYUz0bJKTLBE2VdT8SKmhCFjyBLzRla8bCl5EtLB/S3F/isD0CAwEAAQ==
甲方私钥:MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAnu8SgxAWdJmry0grJ1PF5lBluDcTNn66iowHrFhTPRskpMsETZV1PxIqaEIWPIEvNGVrxsKXkS0sH9LcX+KwPQIDAQABAkAePbMyCP+c1BiiJ2s+omwHdMjGEoSvW9G2xwo2ut+rwo+UiKX/OXtjggNL32sOG/VBpmwQnCzhHXlM3Uf/AyLBAiEA0j02vlbqrkb4eLLTX/K1ZXk05xFMaxjCfqIdv9VwqykCIQDBhxD/jP48lN/I/cNQjg4710e46gL5U3TvDfmpXZYS9QIgYAHkRfebJAr03OmM7XwAql43cm3L3/xmlT2jKD9oPEECIBAgRh1VTVYU/bTM2Hqc67i2zqYs8cR+3M6StowTXU8FAiAp+LnIyULp1obJN9ZnLRv5RldROa9Evj94cfDq3gu+QQ==
甲方:使用甲方私钥加密消息:lK3A3bNyxV1xc34st8fOtIy5vyjTL1zm7wbU9v5mV21t0hxf1ZLTdvN5+vZPSylF3th0c0KqSdGNLpaazvEYSg==
乙方:使用甲方公钥解密消息:我是阿汤哥
乙方:使用甲方公钥加密消息:msiUhALltZYWQdpDWpp6X4wmDCR3ZVGw4d3AqYBnnwDloNDBivpBhT4LgWseX7x74GpgKFA1g/mpsKCIoXqOiw==
甲方:使用甲方私钥解密消息:Hello, 阿汤哥

3. 常用非对称加密算法 - ElGamal

甲方(发送者) 乙方(接收者) 1. 构建密钥对 2. 发布公钥 3. 使用乙方公钥加密数据 4. 发送加密数据 5. 使用私钥解密数据 甲方(发送者) 乙方(接收者)

代码实现

public static final String KEY_ALGORITHM = "ElGamal";
public static final int KEY_SIZE = 256;
public static final String PUBLIC_KEY = "ElGamalPublicKey";
public static final String PRIVATE_KEY = "ElGamalPrivateKey";

/**
 * 生成甲方密钥对(含公钥、私钥)
 *
 * @return map
 * @throws Exception 异常
 */
public Map<String, Object> initKey() throws Exception {
    // 加入BouncyCastleProvider支持
    Security.addProvider(new BouncyCastleProvider());
    // 实例化算法参数生成器
    final AlgorithmParameterGenerator apg = AlgorithmParameterGenerator.getInstance(KEY_ALGORITHM);
    // 初始化算法生成器
    apg.init(KEY_SIZE);
    // 生成算法参数
    final AlgorithmParameters parameters = apg.generateParameters();
    // 构建参数材料
    final DHParameterSpec dhParameterSpec = parameters.getParameterSpec(DHParameterSpec.class);
    // 实例化密钥对生成器
    final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
    keyPairGenerator.initialize(dhParameterSpec, new SecureRandom());

    // 生成密钥对
    final KeyPair keyPair = keyPairGenerator.generateKeyPair();
    // 获取公钥
    final PublicKey publicKey = keyPair.getPublic();
    // 获取私钥
    final PrivateKey privateKey = keyPair.getPrivate();

    // 构造返回map
    Map<String, Object> keyMap = new HashMap<>();
    keyMap.put(PUBLIC_KEY, publicKey);
    keyMap.put(PRIVATE_KEY, privateKey);

    return keyMap;
}

/**
 * 取得公钥
 *
 * @param keyMap 密钥map
 * @return 公钥
 */
public byte[] getPublicKey(Map<String, Object> keyMap) {
    final Key key = (Key) keyMap.get(PUBLIC_KEY);
    return key.getEncoded();
}

/**
 * 取得私钥
 *
 * @param keyMap 密钥map
 * @return 私钥
 */
public byte[] getPrivateKey(Map<String, Object> keyMap) {
    final Key key = (Key) keyMap.get(PRIVATE_KEY);
    return key.getEncoded();
}
/**
 * 使用公钥加密数据
 *
 * @param data      待解密数据
 * @param publicKey 公钥
 * @return 解密后数据
 */
public byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
    Security.addProvider(new BouncyCastleProvider());
    // 获取公钥
    final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey);
    final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    // 生成公钥
    final PublicKey pubKey = keyFactory.generatePublic(x509EncodedKeySpec);
    // 数据加密
    final Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    cipher.init(Cipher.ENCRYPT_MODE, pubKey);
    return cipher.doFinal(data);
}

/**
 * 使用私钥解密数据
 *
 * @param data       待加密数据
 * @param privateKey 私钥
 * @return 加密后数据
 */
public byte[] decryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {
    Security.addProvider(new BouncyCastleProvider());
    // 获取私钥
    final PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey);
    final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    // 生成私钥
    final PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
    // 数据加密
    final Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    cipher.init(Cipher.DECRYPT_MODE, priKey);
    return cipher.doFinal(data);
}
@Test
public void testRSA() throws Exception {
    Security.addProvider(new BouncyCastleProvider());

    final Map<String, Object> bKeyMap = initKey();
    final byte[] bPublicKey = getPublicKey(bKeyMap);
    final byte[] bPrivateKey = getPrivateKey(bKeyMap);
    System.out.println("乙方公钥:" + Base64.toBase64String(bPublicKey));
    System.out.println("乙方私钥:" + Base64.toBase64String(bPrivateKey));

    final byte[] aEncrypt = encryptByPublicKey("我是阿汤哥".getBytes(), bPublicKey);
    final byte[] bDecrypt = decryptByPrivateKey(aEncrypt, bPrivateKey);
    System.out.println("甲方:使用乙方公钥加密消息:" + Base64.toBase64String(aEncrypt));
    System.out.println("乙方:使用乙方私钥解密消息:" + new String(bDecrypt));
}

执行结果

乙方公钥:MHYwTwYGKw4HAgEBMEUCIQD3Tow0iMrSnqcab/qk3sixGNZsFqerw5TZS8AthdG9/wIgVwGItAIOERVrOUQuvYUf4iBgNedVcIVEMpmCAAF67GsDIwACICuSrF+jA6g2XGfFjtP8zmZWA0LstwQQgsMBB6AYuA1/
乙方私钥:MHgCAQAwTwYGKw4HAgEBMEUCIQD3Tow0iMrSnqcab/qk3sixGNZsFqerw5TZS8AthdG9/wIgVwGItAIOERVrOUQuvYUf4iBgNedVcIVEMpmCAAF67GsEIgIgS99qTF3QgAjIKNcpPaA5jnTSp6AUOqb1XhOGGtr75iw=
甲方:使用乙方公钥加密消息:3sdh+pOViDQWU8aDO/LC1SnK427qrFc8PHrMVyE+k7MbL7tQHbq+5I7MZ0vz7WAc6ysAvVZU9pg8YcQvoYWoEw==
乙方:使用乙方私钥解密消息:我是阿汤哥
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值