The following Java code illustrates how to encrypt and decrypt with RSA.
import java.math.BigInteger; public class RdpRsaEncrypt{
//
// Print out the contents of a byte array in hexadecimal.
//
private static void PrintBytes(
byte[] bytes
)
{
int cBytes = bytes.length;
int iByte = 0; for (;;) {
for (int i = 0; i < 8; i++) {
String hex = Integer.toHexString(bytes[iByte++] & 0xff);
if (hex.length() == 1) {
hex = "0" + hex;
} System.out.print("0x" + hex + " ");
if (iByte >= cBytes) {
System.out.println();
return;
}
}
System.out.println();
}
} //
// Reverse the order of the values in a byte array.
//
public static void ReverseByteArray(
byte[] array
)
{
int i, j;
byte temp; for (i = 0, j = array.length – 1; i < j; i++, j–) {
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
} //
// Use RSA to encrypt data.
//
public static byte[] RsaEncrypt(
byte[] modulusBytes,
byte[] exponentBytes,
byte[] dataBytes
)
{
//
// Reverse the passed in byte arrays and then use these to
// create the BigIntegers for the RSA computation.
//
ReverseByteArray(modulusBytes);
ReverseByteArray(exponentBytes);
ReverseByteArray(dataBytes); BigInteger modulus = new BigInteger(
1,
modulusBytes
);
BigInteger exponent = new BigInteger(
1,
exponentBytes
);
BigInteger data = new BigInteger(
1,
dataBytes
); //
// Perform RSA encryption:
// ciphertext = plaintext^exponent % modulus.
//
BigInteger cipherText = data.modPow(
exponent,
modulus
); //
// Reverse the generated ciphertext.
//
byte[] cipherTextBytes = cipherText.toByteArray();
ReverseByteArray(cipherTextBytes); //
// Undo the reversal of the passed in byte arrays.
//
ReverseByteArray(modulusBytes);
ReverseByteArray(exponentBytes);
ReverseByteArray(dataBytes); return cipherTextBytes;
}
//
// Use RSA to decrypt data.
//
public static byte[] RsaDecrypt(
byte[] modulusBytes,
byte[] privateExponentBytes,
byte[] encryptedDataBytes
)
{
//
// Reverse the passed in byte arrays and then use these to
// create the BigIntegers for the RSA computation.
//
ReverseByteArray(modulusBytes);
ReverseByteArray(privateExponentBytes);
ReverseByteArray(encryptedDataBytes); BigInteger modulus = new BigInteger(
1,
modulusBytes
);
BigInteger privateExponent = new BigInteger(
1,
privateExponentBytes
);
BigInteger encryptedData = new BigInteger(
1,
encryptedDataBytes
); //
// Perform RSA encryption:
// plaintext = ciphertext^privateExponent % modulus.
//
BigInteger decryptedData = encryptedData.modPow(
privateExponent,
modulus
); //
// Reverse the generated plaintext.
//
byte[] decryptedDataBytes = decryptedData.toByteArray();
ReverseByteArray(decryptedDataBytes); //
// Undo the reversal of the passed in byte arrays.
//
ReverseByteArray(modulusBytes);
ReverseByteArray(privateExponentBytes);
ReverseByteArray(encryptedDataBytes); return decryptedDataBytes;
} //
// Main routine.
//
public static void main(
String[] args
)
{
//
// Modulus bytes obtained straight from the wire in the
// proprietary certificate (in little endian format).
// This is for a 512-bit key set.
//
byte[] modulusBytes =
{
(byte) 0x37, (byte) 0xa8, (byte) 0x70, (byte) 0xfe,
(byte) 0x9a, (byte) 0xb9, (byte) 0xa8, (byte) 0x54,
(byte) 0xcb, (byte) 0x98, (byte) 0x79, (byte) 0x44,
(byte) 0x7a, (byte) 0xb9, (byte) 0xeb, (byte) 0x38,
(byte) 0x06, (byte) 0xea, (byte) 0x26, (byte) 0xa1,
(byte) 0x47, (byte) 0xea, (byte) 0x19, (byte) 0x70,
(byte) 0x5d, (byte) 0xf3, (byte) 0x52, (byte) 0x88,
(byte) 0x70, (byte) 0x21, (byte) 0xb5, (byte) 0x9e,
(byte) 0x50, (byte) 0xb4, (byte) 0xe1, (byte) 0xf5,
(byte) 0x1a, (byte) 0xd8, (byte) 0x2d, (byte) 0x51,
(byte) 0x4d, (byte) 0x1a, (byte) 0xad, (byte) 0x79,
(byte) 0x7c, (byte) 0x89, (byte) 0x46, (byte) 0xb0,
(byte) 0xcc, (byte) 0x66, (byte) 0x74, (byte) 0x02,
(byte) 0xd8, (byte) 0x28, (byte) 0x5d, (byte) 0x9d,
(byte) 0xd7, (byte) 0xca, (byte) 0xfc, (byte) 0x60,
(byte) 0x0f, (byte) 0x38, (byte) 0xf9, (byte) 0xb3
}; //
// Exponent bytes (in little endian order) obtained straight
// from the wire (in the proprietary certificate).
//
byte[] exponentBytes =
{
(byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x00
}; //
// Private exponent of the private key generated by the
// server (in little endian format).
//
byte[] privateExponentBytes =
{
(byte) 0xc1, (byte) 0x07, (byte) 0xe7, (byte) 0xd4,
(byte) 0xd3, (byte) 0x38, (byte) 0x8d, (byte) 0x36,
(byte) 0xf5, (byte) 0x9e, (byte) 0x8b, (byte) 0x96,
(byte) 0x0d, (byte) 0x55, (byte) 0x65, (byte) 0x08,
(byte) 0x28, (byte) 0x25, (byte) 0xa3, (byte) 0x2e,
(byte) 0xc7, (byte) 0x68, (byte) 0xd6, (byte) 0x44,
(byte) 0x85, (byte) 0x2d, (byte) 0x32, (byte) 0xf6,
(byte) 0x72, (byte) 0xa8, (byte) 0x9b, (byte) 0xba,
(byte) 0x5e, (byte) 0x82, (byte) 0x82, (byte) 0xf0,
(byte) 0x5c, (byte) 0x0c, (byte) 0xeb, (byte) 0x6b,
(byte) 0x12, (byte) 0x6a, (byte) 0xa7, (byte) 0x45,
(byte) 0x15, (byte) 0xce, (byte) 0x41, (byte) 0xe0,
(byte) 0x03, (byte) 0xe5, (byte) 0xe6, (byte) 0x6d,
(byte) 0xdf, (byte) 0xfd, (byte) 0x58, (byte) 0x61,
(byte) 0x0b, (byte) 0x07, (byte) 0xa4, (byte) 0x7b,
(byte) 0xb3, (byte) 0xf3, (byte) 0x71, (byte) 0x94
}; //
// Sample 32-byte client random.
//
byte[] clientRandomBytes =
{
(byte) 0xff, (byte) 0xee, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xff
}; System.out.println("Client random:");
PrintBytes(clientRandomBytes); //
// Perform encryption.
//
byte[] encryptedClientRandomBytes = RsaEncrypt(
modulusBytes,
exponentBytes,
clientRandomBytes
); System.out.println("Encrypted client random:");
PrintBytes(encryptedClientRandomBytes); //
// Perform decryption.
//
byte[] decryptedClientRandomBytes = RsaDecrypt(
modulusBytes,
privateExponentBytes,
encryptedClientRandomBytes
); System.out.println("Decrypted client random:");
PrintBytes(decryptedClientRandomBytes);
}
};