Add RSA key I/O tests

master
Graham 5 years ago
parent dcfaedcd2f
commit 1cdf67e182
  1. 4
      common/pom.xml
  2. 129
      common/src/test/java/dev/openrs2/common/crypto/RsaTest.kt
  3. 6
      pom.xml

@ -19,6 +19,10 @@
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.google.jimfs</groupId>
<artifactId>jimfs</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.michael-bull.kotlin-inline-logger</groupId> <groupId>com.michael-bull.kotlin-inline-logger</groupId>
<artifactId>kotlin-inline-logger-jvm</artifactId> <artifactId>kotlin-inline-logger-jvm</artifactId>

@ -1,16 +1,46 @@
package dev.openrs2.common.crypto package dev.openrs2.common.crypto
import com.google.common.jimfs.Jimfs
import io.netty.buffer.Unpooled import io.netty.buffer.Unpooled
import org.bouncycastle.crypto.params.RSAKeyParameters import org.bouncycastle.crypto.params.RSAKeyParameters
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters
import org.bouncycastle.util.Properties import org.bouncycastle.util.Properties
import java.math.BigInteger import java.math.BigInteger
import java.nio.file.Files
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
object RsaTest { object RsaTest {
private const val ALLOW_UNSAFE_MOD = "org.bouncycastle.rsa.allow_unsafe_mod" 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 @Test
fun testGenerateKeyPair() { fun testGenerateKeyPair() {
val (public, private) = Rsa.generateKeyPair() val (public, private) = Rsa.generateKeyPair()
@ -24,45 +54,27 @@ object RsaTest {
@Test @Test
fun testEncrypt() { fun testEncrypt() {
// from https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Example val ciphertext = Rsa.encrypt(BigInteger("65"), PUBLIC_KEY)
val public = allowUnsafeMod { RSAKeyParameters(false, BigInteger("3233"), BigInteger("17")) }
val ciphertext = Rsa.encrypt(BigInteger("65"), public)
assertEquals(BigInteger("2790"), ciphertext) assertEquals(BigInteger("2790"), ciphertext)
} }
@Test @Test
fun testDecrypt() { fun testDecrypt() {
// from https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Example val ciphertext = Rsa.decrypt(BigInteger("2790"), PRIVATE_KEY)
val public = allowUnsafeMod { RSAKeyParameters(true, BigInteger("3233"), BigInteger("413")) }
val ciphertext = Rsa.decrypt(BigInteger("2790"), public)
assertEquals(BigInteger("65"), ciphertext) assertEquals(BigInteger("65"), ciphertext)
} }
@Test @Test
fun testDecryptCrt() { fun testDecryptCrt() {
// from https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Example val ciphertext = Rsa.decrypt(BigInteger("2790"), PRIVATE_KEY_CRT)
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)
assertEquals(BigInteger("65"), ciphertext) assertEquals(BigInteger("65"), ciphertext)
} }
@Test @Test
fun testEncryptByteBuf() { 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)) val plaintext = Unpooled.wrappedBuffer(byteArrayOf(65))
try { try {
val ciphertext = plaintext.rsaEncrypt(public) val ciphertext = plaintext.rsaEncrypt(PUBLIC_KEY)
try { try {
val expectedCiphertext = Unpooled.wrappedBuffer(byteArrayOf(10, 230.toByte())) val expectedCiphertext = Unpooled.wrappedBuffer(byteArrayOf(10, 230.toByte()))
try { try {
@ -80,12 +92,9 @@ object RsaTest {
@Test @Test
fun testDecryptByteBuf() { 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())) val ciphertext = Unpooled.wrappedBuffer(byteArrayOf(10, 230.toByte()))
try { try {
val plaintext = ciphertext.rsaDecrypt(private) val plaintext = ciphertext.rsaDecrypt(PRIVATE_KEY)
try { try {
val expectedPlaintext = Unpooled.wrappedBuffer(byteArrayOf(65)) val expectedPlaintext = Unpooled.wrappedBuffer(byteArrayOf(65))
try { 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 <T> allowUnsafeMod(f: () -> T): T { private fun <T> allowUnsafeMod(f: () -> T): T {
Properties.setThreadOverride(ALLOW_UNSAFE_MOD, true) Properties.setThreadOverride(ALLOW_UNSAFE_MOD, true)
try { try {

@ -58,6 +58,12 @@
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
<version>28.2-jre</version> <version>28.2-jre</version>
</dependency> </dependency>
<dependency>
<groupId>com.google.jimfs</groupId>
<artifactId>jimfs</artifactId>
<version>1.1</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>com.github.javaparser</groupId> <groupId>com.github.javaparser</groupId>
<artifactId>javaparser-symbol-solver-core</artifactId> <artifactId>javaparser-symbol-solver-core</artifactId>

Loading…
Cancel
Save