Skip to content

Commit

Permalink
feat(app): RSA支持padding选择,新增Skein-256-128
Browse files Browse the repository at this point in the history
  • Loading branch information
Leon406 committed Apr 18, 2022
1 parent f5597d2 commit 4d0d9c2
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 56 deletions.
1 change: 1 addition & 0 deletions app/src/main/kotlin/me/leon/Digests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ val ALGOS_HASH =
"DSTU7564" to listOf("256", "384", "512"),
"Skein" to
listOf(
"256-128",
"256-160",
"256-224",
"256-256",
Expand Down
49 changes: 34 additions & 15 deletions app/src/main/kotlin/me/leon/ext/crypto/AsymmetircCrypto.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,28 @@ import org.bouncycastle.pqc.crypto.lms.LMSigParameters
import org.bouncycastle.pqc.jcajce.spec.LMSKeyGenParameterSpec
import org.bouncycastle.pqc.jcajce.spec.SPHINCSPlusParameterSpec

val ASYMMETRIC_ALGOS = mapOf(
"RSA" to listOf(512, 1024, 2048, 3072, 4096),
"ElGamal" to listOf(512, 1024, 2048),
"SM2" to listOf(256),
)

val RSA_PADDINGS = listOf(
"PKCS1Padding",
"NoPadding",
"OAEPWithMD5AndMGF1Padding",
"OAEPWithSHA1AndMGF1Padding",
"OAEPWithSHA224AndMGF1Padding",
"OAEPWithSHA256AndMGF1Padding",
"OAEPWithSHA384AndMGF1Padding",
"OAEPWithSHA512AndMGF1Padding",
"OAEPWithSHA3-224AndMGF1Padding",
"OAEPWithSHA3-256AndMGF1Padding",
"OAEPWithSHA3-384AndMGF1Padding",
"OAEPWithSHA3-512AndMGF1Padding",
"ISO9796-1Padding",
)

fun String.removePemInfo() =
replace("---+(?:END|BEGIN) (?:RSA )?\\w+ KEY---+|\n|\r|\r\n".toRegex(), "")

Expand Down Expand Up @@ -114,7 +136,7 @@ fun ByteArray.privateDecrypt(
alg: String,
): ByteArray = asymmetricDecrypt(key.toPrivateKey(alg), alg)

fun ByteArray.asymmtricEncrypt(key: Key?, alg: String, reserved: Int = 11): ByteArray =
fun ByteArray.asymmetricEncrypt(key: Key?, alg: String, reserved: Int = 11): ByteArray =
Cipher.getInstance(alg).run {
init(Cipher.ENCRYPT_MODE, key)
val bitLen =
Expand All @@ -136,30 +158,27 @@ fun ByteArray.asymmtricEncrypt(key: Key?, alg: String, reserved: Int = 11): Byte
}

fun ByteArray.privateEncrypt(key: String, alg: String, reserved: Int = 11): ByteArray =
asymmtricEncrypt(key.toPrivateKey(alg), alg, reserved)
asymmetricEncrypt(key.toPrivateKey(alg), alg, reserved)

fun PublicKey.bitLength() = (this as? RSAPublicKey)?.modulus?.bitLength() ?: 1024

fun PrivateKey.bitLength() = (this as? RSAPrivateKey)?.modulus?.bitLength() ?: 1024

/** 生成密钥对 private key pkcs8 */
fun genKeys(alg: String, keySize: Int) =
KeyPairGenerator.getInstance(alg).run {
KeyPairGenerator.getInstance(if (alg.contains("/")) alg.substringBefore('/') else alg).run {
initialize(keySize)
val keyPair = generateKeyPair()
val publicKey = keyPair.public
val privateKey = keyPair.private
arrayOf(publicKey.encoded.base64(), privateKey.encoded.base64())
}

val ASYMMETRIC_ALG =
mapOf(
"RSA" to listOf(512, 1024, 2048, 3072, 4096),
"SM2" to listOf(256),
"ElGamal" to listOf(512, 1024, 2048)
)

private fun String.properKeyPairAlg() = takeUnless { it.equals("SM2", true) } ?: "EC"
private fun String.properKeyPairAlg() = when {
this == "SM2" -> "EC"
this.startsWith("RSA") -> "RSA"
else -> this
}

private val ecGenParameterSpec =
mapOf(
Expand Down Expand Up @@ -211,7 +230,7 @@ fun genKeys(alg: String, params: List<Any> = emptyList()) =

fun checkKeyPair(pub: String, pri: String, alg: String = "RSA"): Boolean {
val testData = byteArrayOf(67)
return testData.asymmtricEncrypt(pub.toPublicKey(alg), alg).run {
return testData.asymmetricEncrypt(pub.toPublicKey(alg), alg).run {
asymmetricDecrypt(pri.toPrivateKey(alg), alg).contentEquals(testData)
}
}
Expand All @@ -225,9 +244,9 @@ fun pkcs8ToPkcs1(pkcs8: String) =

fun pkcs1ToPkcs8(pkcs1: String) =
PrivateKeyInfo(
AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption),
ASN1Primitive.fromByteArray(pkcs1.base64Decode())
)
AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption),
ASN1Primitive.fromByteArray(pkcs1.base64Decode())
)
.encoded
.run {
PKCS8EncodedKeySpec(this).run {
Expand Down
1 change: 1 addition & 0 deletions app/src/main/kotlin/me/leon/ext/crypto/MACs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ object MACs {
"HmacDSTU7564" to listOf("256", "384", "512"),
"HmacSkein" to
listOf(
"256-128",
"256-160",
"256-224",
"256-256",
Expand Down
87 changes: 48 additions & 39 deletions app/src/main/kotlin/me/leon/view/AsymmetricCryptoView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ class AsymmetricCryptoView : Fragment(FX.messages["asymmetric"]) {
private val isSingleLine = SimpleBooleanProperty(false)
private val privateKeyEncrypt = SimpleBooleanProperty(false)
private val isProcessing = SimpleBooleanProperty(false)
private var cbBits :ComboBox<Number> by singleAssign()
private val isEnablePadding = SimpleBooleanProperty(true)

private var cbBits: ComboBox<Number> by singleAssign()
lateinit var taInput: TextArea
lateinit var taKey: TextArea
lateinit var taOutput: TextArea
Expand All @@ -38,6 +40,7 @@ class AsymmetricCryptoView : Fragment(FX.messages["asymmetric"]) {
if (privateKeyEncrypt.get()) "private key encrypt"
else "public key encrypt"
} cost: $timeConsumption ms"
private val selectedPadding = SimpleStringProperty(RSA_PADDINGS.first())
private lateinit var labelInfo: Label
private var keyText: String
get() =
Expand All @@ -51,22 +54,19 @@ class AsymmetricCryptoView : Fragment(FX.messages["asymmetric"]) {
}

private val alg
get() = selectedAlg.get()
get() = with(selectedAlg.get()) {
if (this == "RSA") "$this/NONE/${selectedPadding.get()}"
else this
}
private var isEncrypt = true
private var inputEncode = "raw"
private var outputEncode = "base64"
private lateinit var tgInput: ToggleGroup
private lateinit var tgOutput: ToggleGroup
private val algoMaps = mapOf(
"RSA" to listOf(512, 1024, 2048, 3072, 4096),
"ElGamal" to listOf(512, 1024, 2048),
"SM2" to listOf(256),

)
private val bitsLists = mutableListOf(512, 1024, 2048, 3072, 4096)
private val algs = algoMaps.keys.toMutableList()
private val algs = ASYMMETRIC_ALGOS.keys.toMutableList()
private val selectedAlg = SimpleStringProperty(algs.first())
private val selectedBits = SimpleIntegerProperty(algoMaps[selectedAlg.get()]!!.first())
private val selectedBits = SimpleIntegerProperty(ASYMMETRIC_ALGOS[selectedAlg.get()]!!.first())
private val isPrivateKey
get() = isEncrypt && privateKeyEncrypt.get() || !isEncrypt && !privateKeyEncrypt.get()

Expand All @@ -89,12 +89,12 @@ class AsymmetricCryptoView : Fragment(FX.messages["asymmetric"]) {
private fun updateKeySize() {
runAsync {
runCatching {
if (isPrivateKey) {
controller.lengthFromPri(keyText)
} else {
controller.lengthFromPub(keyText)
}
if (isPrivateKey) {
controller.lengthFromPri(keyText)
} else {
controller.lengthFromPub(keyText)
}
}
.getOrDefault(1024)
} ui { selectedBits.set(it) }
}
Expand Down Expand Up @@ -159,13 +159,22 @@ class AsymmetricCryptoView : Fragment(FX.messages["asymmetric"]) {
combobox(selectedAlg, algs) { cellFormat { text = it.toString() } }
selectedAlg.addListener { _, _, newValue ->
newValue?.run {
cbBits.items = algoMaps[newValue]!!.asObservable()
selectedBits.set(algoMaps[newValue]!!.first())
cbBits.isDisable = algoMaps[newValue]!!.size == 1
cbBits.items = ASYMMETRIC_ALGOS[newValue]!!.asObservable()
selectedBits.set(ASYMMETRIC_ALGOS[newValue]!!.first())
cbBits.isDisable = ASYMMETRIC_ALGOS[newValue]!!.size == 1
isEnablePadding.value = newValue == "RSA"
}
}
label(messages["bits"])
cbBits = combobox(selectedBits, bitsLists) { cellFormat { text = it.toString() } }
cbBits = combobox(selectedBits, ASYMMETRIC_ALGOS[selectedAlg.get()]) { cellFormat { text = it.toString() } }
label("padding:")
combobox(selectedPadding, RSA_PADDINGS) {
enableWhen(isEnablePadding)
cellFormat { text = it }
}
}
hbox {
addClass(Styles.center)
togglegroup {
spacing = DEFAULT_SPACING
radiobutton(messages["encrypt"]) { isSelected = true }
Expand All @@ -187,27 +196,27 @@ class AsymmetricCryptoView : Fragment(FX.messages["asymmetric"]) {
action {
isProcessing.value = true
runAsync { genKeys(alg, listOf(selectedBits.value.toInt())) } ui
{
isProcessing.value = false
if (isPrivateKey) {
taInput.text = it[0]
taKey.text = it[1]
} else {
taInput.text = it[1]
taKey.text = it[0]
{
isProcessing.value = false
if (isPrivateKey) {
taInput.text = it[0]
taKey.text = it[1]
} else {
taInput.text = it[1]
taKey.text = it[0]
}
}
}
}
}
button(messages["deriveKey"]) {
enableWhen(!isProcessing)
action {
isProcessing.value = true
runAsync { catch({ it }) { taKey.text.privateKeyDerivedPublicKey(alg) } } ui
{
isProcessing.value = false
taOutput.text = it
}
{
isProcessing.value = false
taOutput.text = it
}
}
}
}
Expand Down Expand Up @@ -293,12 +302,12 @@ class AsymmetricCryptoView : Fragment(FX.messages["asymmetric"]) {
outputEncode
)
} ui
{
isProcessing.value = false
outputText = it
timeConsumption = System.currentTimeMillis() - startTime
labelInfo.text = info
if (Prefs.autoCopy) it.copy().also { primaryStage.showToast(messages["copied"]) }
}
{
isProcessing.value = false
outputText = it
timeConsumption = System.currentTimeMillis() - startTime
labelInfo.text = info
if (Prefs.autoCopy) it.copy().also { primaryStage.showToast(messages["copied"]) }
}
}
}
4 changes: 2 additions & 2 deletions app/src/test/kotlin/me/leon/asymmetric/Asymmetric.kt
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,14 @@ class Asymmetric {

val testData = byteArrayOf(67)
testData
.asymmtricEncrypt(pub.toPublicKey(alg), alg)
.asymmetricEncrypt(pub.toPublicKey(alg), alg)
.run { asymmetricDecrypt(pri.toPrivateKey(alg), alg).contentEquals(testData) }
.also { println(it) }

val pubKey = pub.toPublicKey(alg).also { println(it?.encoded?.base64()) }

val priKey = pri.toPrivateKey(alg).also { println(it?.encoded?.base64()) }
"hello".toByteArray().asymmtricEncrypt(pubKey, "SM2").also {
"hello".toByteArray().asymmetricEncrypt(pubKey, "SM2").also {
println(it.base64())
it.asymmetricDecrypt(priKey, "SM2").also { println(it.decodeToString()) }
}
Expand Down
1 change: 1 addition & 0 deletions app/src/test/kotlin/me/leon/hash/HashTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ class HashTest {
"DSTU7564-512" to
"e83945c9b56620e48b50eaf381c801078e05b89d85043ed5790596584d7057801" +
"73c9d07ac2f0c559f05893d13ea9576d660ac0db5bb8885fac30a07a24ec51a",
"Skein-256-128" to "dfb6780585fcb71b7f8725f3b8bc3db5",
"Skein-256-160" to "69bc779ef32b63ed641594cac645e9cf3540aa8f",
"Skein-256-224" to "71a135876f540e96dc9b429ac733a55f6459e7bfe53f565bca800937",
"Skein-256-256" to "86177f9baa4bd5466585a4fd78b3ebd595d83b29b7c1be57807165c36e42ff26",
Expand Down

0 comments on commit 4d0d9c2

Please sign in to comment.