Skip to content

Instantly share code, notes, and snippets.

@cntsw cntsw/RsaTest.java
Created Mar 9, 2019

Embed
What would you like to do?
Rea Arithmetic Java Demo
public class RsaTest {
private static final BigInteger N1 = new BigInteger("-1"); // -1
public void test() {
int keyByteLen = 128 / 8;
BigInteger p = new BigInteger("fd6a04e98167dfa3", 16);
BigInteger q = new BigInteger("d6b703bcfe619b63", 16);
BigInteger n = p.multiply(q); // 0x282522173461889495699110463826178747657
BigInteger phi = p.add(N1).multiply(q.add(N1)); // phi = (q-1) * (p-1) d48bca9808d27e0d47237bf3e68cb204
BigInteger e = new BigInteger("65537");
BigInteger d = new BigInteger("aaafd074a3b116956729b1e33ea48259", 16);
PublicKey publicKey = new PublicKey(n, e, keyByteLen);
PrivateKey privateKey = new PrivateKey(n, d, keyByteLen);
// encrypt & decrypt
String msg = "hello";
BigInteger crypto = encrypt(publicKey, "hello");
String _msg = decrypt(privateKey, crypto);
assert msg.equals(_msg);
}
private BigInteger encrypt(PublicKey publicKey, String message) {
byte[] msgByte = message.getBytes(); // 获取 message 的编码 (英文字母为ascii编码)
if (msgByte.length > (publicKey.keyByteLen - 11)) {
throw new IllegalArgumentException("message too long");
}
int randomBytesLen = publicKey.keyByteLen - msgByte.length - 3;
byte[] randomPad = genRandomByte(randomBytesLen);
// 填充随机数, 开头固定是 0x0002 中间填充非0随机字节 0x00 表示结尾, 剩余部分追加被加密消息
byte[] paddedByte = new byte[publicKey.keyByteLen];
paddedByte[0] = 0x00;
paddedByte[1] = 0x02;
System.arraycopy(randomPad, 0, paddedByte, 2, randomBytesLen);
paddedByte[randomBytesLen + 2] = 0x00;
System.arraycopy(msgByte, 0, paddedByte, randomBytesLen + 3, msgByte.length);
BigInteger m = new BigInteger(paddedByte); // 直接把字节当做整数, hello -> 68656c6c6f
return m.modPow(publicKey.e, publicKey.n);
}
private String decrypt(PrivateKey privateKey, BigInteger crypto) {
BigInteger m = crypto.modPow(privateKey.d, privateKey.n);
byte[] paddedBytes = m.toByteArray();
assert paddedBytes[0] == 0x02; // 忽略第一位0x00
int msgStart = 2;
for (; msgStart < paddedBytes.length; msgStart++) {
if (paddedBytes[msgStart] == 0) {
msgStart++;
break;
}
}
byte[] msgBytes = Arrays.copyOfRange(paddedBytes, msgStart, paddedBytes.length);
return new String(msgBytes);
}
private byte[] genRandomByte(int length) {
Random random = new Random();
byte[] randomBytes = new byte[length];
random.nextBytes(randomBytes);
// 去0
for (int i = 0; i < randomBytes.length; i++) {
while (randomBytes[i] == '\0') {
randomBytes[i] = (byte) random.nextInt();
}
}
return randomBytes;
}
private static class PrivateKey {
BigInteger n;
BigInteger d;
int keyByteLen;
public PrivateKey(BigInteger n, BigInteger d, int keyByteLen) {
this.n = n;
this.d = d;
this.keyByteLen = keyByteLen;
}
}
private static class PublicKey {
BigInteger n;
BigInteger e;
int keyByteLen;
public PublicKey(BigInteger n, BigInteger e, int keyByteLen) {
this.n = n;
this.e = e;
this.keyByteLen = keyByteLen;
}
}
public static void main(String[] args) {
new RsaTest().test();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.