【发布时间】:2015-11-12 15:15:05
【问题描述】:
我正在处理一个需要对纯文本执行数字签名的项目。为此,我对密文执行 RSA 解密(使用私钥)。 为了验证签名,我计算了签名的 RSA 加密(使用公钥)并将其与初始密文进行比较。 如果相同,则签名有效。 (这基本上是恢复的标志)。
我使用 Java.Security 实现了这一点。 我的问题:恢复的签名与明文完全一样,除了一个 0x00 字节被左填充。 我绝对需要在加密计算中删除这个填充(我不能只取恢复签名的子数组,然后丢弃第一个字节)。
这是我的代码:
主要功能:
public class Test {
/**
* Method main
*
* @param args
*/
public static void main(final String[] args) {
final String plaintext = "6A11541333FF10190123450101c101C8D4302FAE7D436A327276C9D2522AD8141FBF2B8B260FD94AB55E0C0C609A6EFB9D8391088066CA0A817F8E93D4918357C893B5753E32C71DC4FB27B16E2A008F84A928B3D649A5DB4AB7BD97464DACE8A8D4C9AB02B370F60DC703D5C893DC351FC8226E61C8EE0ED5EBAF64320530F662633152955BD1C25851CFF94E432CE89845625820836500062598AD669A6EB317DCF276E1A613C9C70CEA72A40B09C0F09B169D7DAC15A79AFCF154B52331BC";
// Generate a RSA Key Pair
KeyPairGenerator keyGen;
try {
keyGen = KeyPairGenerator.getInstance("RSA");
final RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(1544, RSAKeyGenParameterSpec.F0); // modulus length is 1544, the public exponent is 3
keyGen.initialize(spec);
final KeyPair pair = keyGen.genKeyPair();
final String ciphertext = Utils.toString(Crypto.RSADecrypt(Utils.toBytes(plaintext), pair.getPrivate()));
final String recovery = Utils.toString(Crypto.RSAEncrypt(Utils.toBytes(ciphertext), pair.getPublic()));
System.out.println(recovery);
}
catch (final NoSuchAlgorithmException e) {
e.printStackTrace();
}
catch (final InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
}
}
加密功能:
/**
* Decrypt text using private key.
*
* @param text
* :encrypted text
* @param key
* :The private key
* @return plain text
* @throws java.lang.Exception
*/
public static byte[] RSADecrypt(final byte[] text, final PrivateKey key) {
byte[] plainText = null;
try {
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");
// decrypt the text using the private key
cipher.init(Cipher.DECRYPT_MODE, key);
plainText = cipher.doFinal(text);
}
catch (final Exception ex) {
ex.printStackTrace();
}
return plainText;
}
/**
* Encrypt the plain text using public key.
*
* @param text
* : original plain text
* @param key
* :The public key
* @return Encrypted text
* @throws java.lang.Exception
*/
public static byte[] RSAEncrypt(final byte[] input, final PublicKey key) {
byte[] cipherText = null;
try {
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");
// encrypt the plain text using the public key
cipher.init(Cipher.ENCRYPT_MODE, key);
cipherText = cipher.doFinal(input);
}
catch (final Exception e) {
e.printStackTrace();
}
// return Arrays.copyOfRange(cipherText, 1, cipherText.length); // Ignore the first byte (sign byte)
return cipherText;
}
实用程序:
/**
* Corresponding String chain.
*
* @param bytes
* of bytes (example: apdu response)
* @return Corresponding String chain.<br>
* Example: [(byte)0xEE, (byte)0xFF] -> "EEFF"
*/
public static String toString(final byte[] bytes) {
final char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
final int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[(j * 2) + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
/** A field. */
private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
输出:
006A11541333FF10190123450101C101C8D4302FAE7D436A327276C9D2522AD8141FBF2B8B260FD94AB55E0C0C609A6EFB9D8391088066CA0A817F8E93D4918357C893B5753E32C71DC4FB27B16E2A008F84A928B3D649A5DB4AB7BD97464DACE8A8D4C9AB02B370F60DC703D5C893DC351FC8226E61C8EE0ED5EBAF64320530F662633152955BD1C25851CFF94E432CE89845625820836500062598AD669A6EB317DCF276E1A613C9C70CEA72A40B09C0F09B169D7DAC15A79AFCF154B52331BC
问题: 第一个(0x00)字节来自哪里?我怎样才能将其删除?
非常感谢您的帮助,
克里斯
【问题讨论】:
-
如果您要签名和验证某些内容,为什么不使用Signature 类?它正是针对这种情况而设计的,可以正确处理所有内容,包括生成内容的哈希值。