diff --git a/common/pom.xml b/common/pom.xml
index 114fac17..a472baea 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -19,6 +19,10 @@
com.google.guava
guava
+
+ com.google.jimfs
+ jimfs
+
com.michael-bull.kotlin-inline-logger
kotlin-inline-logger-jvm
diff --git a/common/src/test/java/dev/openrs2/common/crypto/RsaTest.kt b/common/src/test/java/dev/openrs2/common/crypto/RsaTest.kt
index c4b63176..4d997fce 100644
--- a/common/src/test/java/dev/openrs2/common/crypto/RsaTest.kt
+++ b/common/src/test/java/dev/openrs2/common/crypto/RsaTest.kt
@@ -1,16 +1,46 @@
package dev.openrs2.common.crypto
+import com.google.common.jimfs.Jimfs
import io.netty.buffer.Unpooled
import org.bouncycastle.crypto.params.RSAKeyParameters
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters
import org.bouncycastle.util.Properties
import java.math.BigInteger
+import java.nio.file.Files
import kotlin.test.Test
import kotlin.test.assertEquals
+import kotlin.test.assertFalse
+import kotlin.test.assertTrue
object RsaTest {
private const val ALLOW_UNSAFE_MOD = "org.bouncycastle.rsa.allow_unsafe_mod"
+ // example data from https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Example
+ private val PUBLIC_KEY = allowUnsafeMod { RSAKeyParameters(false, BigInteger("3233"), BigInteger("17")) }
+ private val PRIVATE_KEY = allowUnsafeMod { RSAKeyParameters(true, BigInteger("3233"), BigInteger("413")) }
+ private val PRIVATE_KEY_CRT = allowUnsafeMod { RSAPrivateCrtKeyParameters(
+ BigInteger("3233"), // modulus
+ BigInteger("17"), // public exponent
+ BigInteger("413"), // private exponent
+ BigInteger("61"), // p
+ BigInteger("53"), // q
+ BigInteger("53"), // dP
+ BigInteger("49"), // dQ
+ BigInteger("38") // qInv
+ ) }
+
+ private val PUBLIC_KEY_PEM = listOf(
+ "-----BEGIN PUBLIC KEY-----",
+ "MBswDQYJKoZIhvcNAQEBBQADCgAwBwICDKECARE=",
+ "-----END PUBLIC KEY-----"
+ )
+ private val PRIVATE_KEY_PEM = listOf(
+ "-----BEGIN PRIVATE KEY-----",
+ "MDMCAQAwDQYJKoZIhvcNAQEBBQAEHzAdAgEAAgIMoQIBEQICAZ0CAT0CATUCATUC",
+ "ATECASY=",
+ "-----END PRIVATE KEY-----"
+ )
+
@Test
fun testGenerateKeyPair() {
val (public, private) = Rsa.generateKeyPair()
@@ -24,45 +54,27 @@ object RsaTest {
@Test
fun testEncrypt() {
- // from https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Example
- val public = allowUnsafeMod { RSAKeyParameters(false, BigInteger("3233"), BigInteger("17")) }
- val ciphertext = Rsa.encrypt(BigInteger("65"), public)
+ val ciphertext = Rsa.encrypt(BigInteger("65"), PUBLIC_KEY)
assertEquals(BigInteger("2790"), ciphertext)
}
@Test
fun testDecrypt() {
- // from https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Example
- val public = allowUnsafeMod { RSAKeyParameters(true, BigInteger("3233"), BigInteger("413")) }
- val ciphertext = Rsa.decrypt(BigInteger("2790"), public)
+ val ciphertext = Rsa.decrypt(BigInteger("2790"), PRIVATE_KEY)
assertEquals(BigInteger("65"), ciphertext)
}
@Test
fun testDecryptCrt() {
- // from https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Example
- val private = allowUnsafeMod { RSAPrivateCrtKeyParameters(
- BigInteger("3233"), // modulus
- BigInteger("17"), // public exponent
- BigInteger("413"), // private exponent
- BigInteger("61"), // p
- BigInteger("53"), // q
- BigInteger("53"), // dP
- BigInteger("49"), // dQ
- BigInteger("38") // qInv
- ) }
- val ciphertext = Rsa.decrypt(BigInteger("2790"), private)
+ val ciphertext = Rsa.decrypt(BigInteger("2790"), PRIVATE_KEY_CRT)
assertEquals(BigInteger("65"), ciphertext)
}
@Test
fun testEncryptByteBuf() {
- // from https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Example
- val public = allowUnsafeMod { RSAKeyParameters(false, BigInteger("3233"), BigInteger("17")) }
-
val plaintext = Unpooled.wrappedBuffer(byteArrayOf(65))
try {
- val ciphertext = plaintext.rsaEncrypt(public)
+ val ciphertext = plaintext.rsaEncrypt(PUBLIC_KEY)
try {
val expectedCiphertext = Unpooled.wrappedBuffer(byteArrayOf(10, 230.toByte()))
try {
@@ -80,12 +92,9 @@ object RsaTest {
@Test
fun testDecryptByteBuf() {
- // from https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Example
- val private = allowUnsafeMod { RSAKeyParameters(true, BigInteger("3233"), BigInteger("413")) }
-
val ciphertext = Unpooled.wrappedBuffer(byteArrayOf(10, 230.toByte()))
try {
- val plaintext = ciphertext.rsaDecrypt(private)
+ val plaintext = ciphertext.rsaDecrypt(PRIVATE_KEY)
try {
val expectedPlaintext = Unpooled.wrappedBuffer(byteArrayOf(65))
try {
@@ -101,6 +110,74 @@ object RsaTest {
}
}
+ @Test
+ fun testReadPublicKey() {
+ Jimfs.newFileSystem().use { fs ->
+ val file = Files.createTempFile(fs.getPath("/"), "public", ".key")
+ try {
+ Files.write(file, PUBLIC_KEY_PEM)
+
+ val key = allowUnsafeMod { Rsa.readPublicKey(file) }
+ assertFalse(key.isPrivate)
+ assertEquals(PUBLIC_KEY.modulus, key.modulus)
+ assertEquals(PUBLIC_KEY.exponent, key.exponent)
+ } finally {
+ Files.deleteIfExists(file)
+ }
+ }
+ }
+
+ @Test
+ fun testWritePublicKey() {
+ Jimfs.newFileSystem().use { fs ->
+ val file = Files.createTempFile(fs.getPath("/"), "public", ".key")
+ try {
+ Rsa.writePublicKey(file, PUBLIC_KEY)
+
+ assertEquals(PUBLIC_KEY_PEM, Files.readAllLines(file))
+ } finally {
+ Files.deleteIfExists(file)
+ }
+ }
+ }
+
+ @Test
+ fun testReadPrivateKey() {
+ Jimfs.newFileSystem().use { fs ->
+ val file = Files.createTempFile(fs.getPath("/"), "private", ".key")
+ try {
+ Files.write(file, PRIVATE_KEY_PEM)
+
+ val key = allowUnsafeMod { Rsa.readPrivateKey(file) } as RSAPrivateCrtKeyParameters
+ assertTrue(key.isPrivate)
+ assertEquals(PRIVATE_KEY_CRT.modulus, key.modulus)
+ assertEquals(PRIVATE_KEY_CRT.exponent, key.exponent)
+ assertEquals(PRIVATE_KEY_CRT.publicExponent, key.publicExponent)
+ assertEquals(PRIVATE_KEY_CRT.p, key.p)
+ assertEquals(PRIVATE_KEY_CRT.q, key.q)
+ assertEquals(PRIVATE_KEY_CRT.dp, key.dp)
+ assertEquals(PRIVATE_KEY_CRT.dq, key.dq)
+ assertEquals(PRIVATE_KEY_CRT.qInv, key.qInv)
+ } finally {
+ Files.deleteIfExists(file)
+ }
+ }
+ }
+
+ @Test
+ fun testWritePrivateKey() {
+ Jimfs.newFileSystem().use { fs ->
+ val file = Files.createTempFile(fs.getPath("/"), "private", ".key")
+ try {
+ Rsa.writePrivateKey(file, PRIVATE_KEY_CRT)
+
+ assertEquals(PRIVATE_KEY_PEM, Files.readAllLines(file))
+ } finally {
+ Files.deleteIfExists(file)
+ }
+ }
+ }
+
private fun allowUnsafeMod(f: () -> T): T {
Properties.setThreadOverride(ALLOW_UNSAFE_MOD, true)
try {
diff --git a/pom.xml b/pom.xml
index 780d48d7..464f0e93 100644
--- a/pom.xml
+++ b/pom.xml
@@ -58,6 +58,12 @@
guava
28.2-jre
+
+ com.google.jimfs
+ jimfs
+ 1.1
+ test
+
com.github.javaparser
javaparser-symbol-solver-core