公钥可公开发布,用于发送方加密要发送的信息,私钥用于接收方解密接收到的加密内容。公私钥对计算时间较长,主要用于加密较少的数据。常用的非对称加密算法有RSA和ECC。
公有链上交易数据全网可见,公众可以跟踪这些交易,任何人可以通过观察区块链得出关于某事的结论,不利于个人或机构的合法隐私保护。针对该类风险的应对策略是:第一,由认证机构代理用户在区块链上进行交易,用户资料和个人行为不进入区块链。第二,不采用全网广播方式,而是将交易数据的传输限制在正在进行相关交易的节点之间。第三,对用户数据的访问采用权限控制,持有密钥的访问者才能解密和访问数据。第四,采用例如“零知识证明”等隐私保护算法,规避隐私暴露。
/**
* 非对称加密和解密用到的模数(modulus)
*/
private static String modulus = "978C0A92D2173439707498F0944AA476B1B62595877DD6FA87F" +
"E2AC6DCB3D0BF0B82857439C99B5091192BC134889DFF60C562EC54EFBA4FF2F9D55ADBCCEA4" +
"2FBA80CB398ED501280A007C83AF30C3D1A142D6133C63012B90AB26AC60C898FB66EDC3192C3E" +
"C4FF66925A64003B72496099F4F09A9FB72A2CF9E4D770C4";
/**
* 非对称加密用到的加密密钥(component)
*/
private static String exponent = "010001";
/**
* rsa加密对象
*/
private static Cipher cipher;
/**
* 初始化rsa加密对象
*/
static {
byte[] modulusBytes = hexStringToByte(modulus);
byte[] exponentBytes = hexStringToByte(exponent);
BigInteger modulusInteger = new BigInteger(1, modulusBytes);
BigInteger exponentInteger = new BigInteger(1, exponentBytes);
RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulusInteger, exponentInteger);
try {
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(rsaPubKey);
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
/**
* 将字符串进行非对称加密。
*
* @param string
* 要加密的字符串明文
* @return 加密后的字符串
*/
public static String encrypt(String string) {
byte[] cipherData = null;
try {
cipherData = cipher.doFinal(string.getBytes("UTF-8"));
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return byteToHexString(cipherData);
}
/**
* 将字节数组转换为十六进制字符串
*
* @param bytes
* 字节数组
* @return 十六进制字符串
*/
private static String byteToHexString(byte[] bytes) {
String string = new BigInteger(1, bytes).toString(16);
if (string.length() % 2 != 0) {
string = "0" + string;
}
return string;
}
/**
* 将十六进制字符串转换为byte数组
*
* @param hexString
* 十六进制字符串
* @return 转换后的字节数组
*/
private static byte[] hexStringToByte(String hexString) {
byte[] digest = new byte[hexString.length() / 2];
for (int i = 0; i < digest.length; i++) {
String byteString = hexString.substring(2 * i, 2 * i + 2);
int byteValue = Integer.parseInt(byteString, 16);
digest[i] = (byte) byteValue;
}
return digest;
}