helper: massive refinement

pull/94/head
cfig 4 years ago
parent 5cef10203b
commit 19632ce235
No known key found for this signature in database
GPG Key ID: B104C307F0FDABB7

@ -50,13 +50,14 @@ data class AuthBlob(
}
}
fun calcSignature(hash: ByteArray, algorithm_name: String): ByteArray {
private fun calcSignature(hash: ByteArray, algorithm_name: String): ByteArray {
val alg = Algorithms.get(algorithm_name)!!
return if (alg.name == "NONE") {
byteArrayOf()
} else {
val k = CryptoHelper.KeyBox.parse(Files.readAllBytes(Paths.get(alg.defaultKey.replace(".pem", ".pk8")))) as PrivateKey
CryptoHelper.Signer.rawRsa(k, Helper.join(alg.padding, hash))
val k = CryptoHelper.KeyBox.parse2(Files.readAllBytes(Paths.get(alg.defaultKey.replace(".pem", ".pk8")))) as Array<*>
assert(k[0] as Boolean)
CryptoHelper.Signer.rawRsa(k[2] as PrivateKey, Helper.join(alg.padding, hash))
}
}

@ -139,7 +139,7 @@ class AuxBlob(
if (key == null) {
algKey = Files.readAllBytes((Paths.get(alg.defaultKey)))
}
val rsa = CryptoHelper.KeyBox.parse(algKey!!) as RSAPrivateKey //BC RSA
val rsa = (CryptoHelper.KeyBox.parse2(algKey!!) as Array<*>)[2] as RSAPrivateKey //BC RSA
encodedKey = CryptoHelper.KeyBox.encodeRSAkey(rsa)
assert(alg.public_key_num_bytes == encodedKey.size)
} else {

@ -35,14 +35,14 @@ class KeyUtilTest {
fun parseKeys() {
val keyFile = "../" + Algorithms.get("SHA256_RSA2048")!!.defaultKey
println("Key: $keyFile")
val k = CryptoHelper.KeyBox.parse(File(keyFile.replace("pem", "pk8")).readBytes()) as RSAPrivateKey
val k = (CryptoHelper.KeyBox.parse2(File(keyFile.replace("pem", "pk8")).readBytes()) as Array<*>)[2] as RSAPrivateKey
println(k.privateExponent)
println(k.modulus)
val k2 = CryptoHelper.KeyBox.parse(File(keyFile).readBytes()) as org.bouncycastle.asn1.pkcs.RSAPrivateKey
val k2 = (CryptoHelper.KeyBox.parse2(File(keyFile).readBytes()) as Array<*>)[2] as org.bouncycastle.asn1.pkcs.RSAPrivateKey
println(k2.privateExponent)
println(k2.modulus)
//KeyHelper2.parseRsaPk8(FileInputStream(keyFile).readAllBytes())
CryptoHelper.KeyBox.parse(File(keyFile.replace("pem", "pk8")).readBytes())
CryptoHelper.KeyBox.parse2(File(keyFile.replace("pem", "pk8")).readBytes())
}
@Test
@ -87,7 +87,7 @@ class KeyUtilTest {
val expectedSig =
"28e17bc57406650ed78785fd558e7c1861cc4014c900d72b61c03cdbab1039e713b5bb19b556d04d276b46aae9b8a3999ccbac533a1cce00f83cfb83e2beb35ed7329f71ffec04fc2839a9b44e50abd66ea6c3d3bea6705e93e9139ecd0331170db18eba36a85a78bc49a5447260a30ed19d956cb2f8a71f6b19e57fdca43e052d1bb7840bf4c3efb47111f4d77764236d2e013fbf3b2577e4a3e01c9d166a5e890ef96210882e6e88ceca2fe3a2201f4961210d4ec6167f5dfd0e038e4a146f960caecab7d15ba65f6edcf5dbd25f5af543cfb8da4338bdbc872eec3f8e72aa8db679099e70952d3f7176c0b9111bf20ad1390eab1d09a859105816fdf92fbb"
val privkFile = "../" + Algorithms.get("SHA256_RSA2048")!!.defaultKey.replace("pem", "pk8")
val k = CryptoHelper.KeyBox.parse(Files.readAllBytes(Paths.get(privkFile))) as PrivateKey
val k = (CryptoHelper.KeyBox.parse2(Files.readAllBytes(Paths.get(privkFile))) as Array<*>)[2] as PrivateKey
val encData = CryptoHelper.Signer.rawRsa(k, data)
assertEquals(expectedSig, Helper.toHexString(encData))
}
@ -108,7 +108,7 @@ class KeyUtilTest {
Helper.fromHexString("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d0609608648016503040201050004206317a4c8d86accc8258c1ac23ef0ebd18bc3301033")
val signature = Signature.getInstance("NONEwithRSA")
val keyFile = "../" + Algorithms.get("SHA256_RSA2048")!!.defaultKey.replace("pem", "pk8")
val k = CryptoHelper.KeyBox.parse(Files.readAllBytes(Paths.get(keyFile))) as PrivateKey
val k = (CryptoHelper.KeyBox.parse2(Files.readAllBytes(Paths.get(keyFile))) as Array<*>)[2] as PrivateKey
signature.initSign(k)
signature.update(data)
println("data size " + data.size)
@ -194,9 +194,11 @@ class KeyUtilTest {
fun signData() {
val data = KeyUtilTest::class.java.classLoader.getResourceAsStream("data").readAllBytes()
println(Helper.toHexString(data))
val privKey = CryptoHelper.KeyBox.parse(
KeyUtilTest::class.java.classLoader.getResourceAsStream("testkey.pk8").readAllBytes()
//@formatter:off
val privKey = (
(CryptoHelper.KeyBox.parse2(KeyUtilTest::class.java.classLoader.getResourceAsStream("testkey.pk8").readAllBytes()) as Array<*>)[2]
) as PrivateKey
//@formatter:on
println("sha256=" + Helper.toHexString(CryptoHelper.Hasher.sha256(data)))
val signedHash = CryptoHelper.Signer.sha256rsa(data, privKey)
println("Signed Hash: " + Helper.toHexString(signedHash))

@ -35,7 +35,7 @@ class BlobTest {
run {//decode pub key and check
val decodedKey = CryptoHelper.KeyBox.decodeRSAkey(encodedKey)
//val rsa = KeyHelper.parsePemPrivateKeyBC(ByteArrayInputStream(Helper.fromHexString(keyStr))) //BC RSA
val rsa = CryptoHelper.KeyBox.parse(Helper.fromHexString(keyStr)) as RSAPrivateKey //BC RSA
val rsa = (CryptoHelper.KeyBox.parse2(Helper.fromHexString(keyStr)) as Array<*>)[2] as RSAPrivateKey //BC RSA
assert(rsa.modulus.equals(decodedKey.modulus))
assert(rsa.publicExponent.equals(decodedKey.publicExponent))
}

@ -9,10 +9,7 @@ import org.apache.commons.exec.PumpStreamHandler
import org.bouncycastle.pkcs.PKCS10CertificationRequest
import org.bouncycastle.util.io.pem.PemReader
import org.slf4j.LoggerFactory
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.io.InputStreamReader
import java.io.*
import java.math.BigInteger
import java.math.RoundingMode
import java.security.KeyFactory
@ -30,11 +27,40 @@ import javax.crypto.Cipher
class CryptoHelper {
class KeyBox {
companion object {
fun parse(data: ByteArray): Any {
fun parseToPk8(kFile: String): OpenSslHelper.PK8RsaKey {
val inBytes = File(kFile).readBytes()
val k = parse2(inBytes) as Array<*>
val kType = if ((k[1] as String) == "PEM") OpenSslHelper.KeyFormat.PEM else OpenSslHelper.KeyFormat.DER
return when (k[2]) {
is org.bouncycastle.asn1.pkcs.RSAPrivateKey -> {
OpenSslHelper.PK1Key(kType, inBytes).toPk8(OpenSslHelper.KeyFormat.PEM)
}
is java.security.interfaces.RSAPrivateKey -> {
OpenSslHelper.PK8RsaKey(kType, inBytes).let {
if (it.format == OpenSslHelper.KeyFormat.DER) {
it.transform(OpenSslHelper.KeyFormat.DER, OpenSslHelper.KeyFormat.PEM)
} else {
it
}
}
}
else -> {
throw IllegalArgumentException("unknown PK1/PK8 private key")
}
}
}
fun parse2(data: ByteArray): Any {
var bSuccess = false
var retType = "NA"
var ret: Any = false
val p = PemReader(InputStreamReader(ByteArrayInputStream(data))).readPemObject()
return if (p != null) {
if (p != null) {
log.debug("parse PEM: " + p.type)
when (p.type) {
bSuccess = true
retType = "PEM"
ret = when (p.type) {
"RSA PUBLIC KEY" -> {
org.bouncycastle.asn1.pkcs.RSAPublicKey.getInstance(p.content) as org.bouncycastle.asn1.pkcs.RSAPublicKey
}
@ -59,47 +85,58 @@ class CryptoHelper {
}
else -> throw IllegalArgumentException("unsupported type: ${p.type}")
}
return arrayOf(bSuccess, retType, ret)
} else {
var bSuccess = false
var ret: Any = false
//try 1
try {
val spec = PKCS8EncodedKeySpec(data)
val privateKey = KeyFactory.getInstance("RSA").generatePrivate(spec)
log.debug("Parse PKCS8:Private")
ret = privateKey
retType = "RAW"
bSuccess = true
} catch (e: java.security.spec.InvalidKeySpecException) {
log.debug("not PKCS8:Private")
}
if (bSuccess) return ret
if (bSuccess) return arrayOf(bSuccess, retType, ret)
//try 2
try {
log.debug("Parse X509:Public")
val spec = X509EncodedKeySpec(data)
retType = "RAW"
ret = KeyFactory.getInstance("RSA").generatePublic(spec)
bSuccess = true
} catch (e: java.security.spec.InvalidKeySpecException) {
log.debug(e.toString())
log.debug("not X509:Public")
}
if (bSuccess) return ret
if (bSuccess) return arrayOf(bSuccess, retType, ret)
//try 3: jks
try {
val pwdArray = "androiddebugkey".toCharArray()
val envPassword = System.getProperty("password") ?: "secretpassword"
log.warn("trying with password=$envPassword")
val ks = KeyStore.getInstance("JKS")
ks.load(ByteArrayInputStream(data), pwdArray)
ks.load(ByteArrayInputStream(data), envPassword.toCharArray())
ret = ks
retType = "JKS"
bSuccess = true
} catch (e: IOException) {
if (e.toString().contains("Keystore was tampered with, or password was incorrect")) {
log.info("JKS password wrong")
log.info("JKS password wrong #1")
bSuccess = false
retType = "JKS"
ret = KeyStore.getInstance("JKS")
}
if (e.toString().contains("keystore password was incorrect")) {
log.info("JKS password wrong #2")
bSuccess = false
ret = true
retType = "JKS"
ret = KeyStore.getInstance("JKS")
}
}
//at last
return ret
return arrayOf(bSuccess, retType, ret)
}
}
@ -282,4 +319,4 @@ class CryptoHelper {
}
}
}
}
}

@ -1,201 +1,393 @@
@file:Suppress("JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE")
package cfig.helper
import com.google.common.io.Files
import cfig.helper.OpenSslHelper.KeyFormat
import org.bouncycastle.util.io.pem.PemReader
import org.slf4j.LoggerFactory
import java.io.ByteArrayInputStream
import java.io.File
import java.io.InputStreamReader
import java.io.*
import java.security.cert.Certificate
import java.util.*
import kotlin.system.exitProcess
import cfig.helper.OpenSslHelper.KeyFormat
class Launcher {
companion object {
private const val hint1 = "private RSA key -> RSA public key(PEM)"
private const val hint2 = "private RSA key -> RSA public key(DER)"
private const val hint3 = "(PEM) --> (DER)"
private const val hint4 = "RSA private: PK1 <=> PK8(PEM)"
private const val hint5 = "RSA private(PK8): => Public Key(PK8, PEM)"
private const val hint7 = "RSA private: PK1 => PK8(DER)"
private const val hint10 = "PK8 RSA: PEM <=> DER"
private const val hint11 = "RSA public(PK8): PEM => DER"
private const val hintCsr = "PK1 RSA PEM ==> CSR"
private const val hintCrt = "PK1 RSA PEM ==> CRT"
private const val hint22 = "CRT ==> JKS"
private const val hintJks = "Generate JKS"
val allSupportedCommands =
listOf("genrsa", "toPublicKey", "decodePEM", "toPk8", "toPk1", "toJks", "toCsr", "toCrt").toString()
private val log = LoggerFactory.getLogger(Launcher::class.java)
fun help() {
println("Help:")
println("\tcrypo.list")
println("\tcrypto.key.parse <file>")
println("\tcrypto.key.genrsa <key_len> <out>")
println("\tcrypto.key.1 <file>")
println("\tcrypto.key.0 : <key_len> <out>")
println("\tcrypto.key.1 : $hint1")
println("\tcrypto.key.2 : $hint2")
println("\tcrypto.key.3 : $hint3")
println("\tcrypto.key.4 : $hint4")
println("\tcrypto.key.5 : $hint5")
println("\tcrypto.key.7 : $hint7")
println("\tcrypto.key.10 : $hint10")
println("\tcrypto.key.11 : $hint11")
println("\tcrypto.key.22 : $hint22")
println("\tcrypto.key.csr : $hintCsr")
println("\tcrypto.key.21 : $hintCrt")
println("\tcrypto.key.jks : $hintJks")
}
}
}
fun main(args: Array<String>) {
val log = LoggerFactory.getLogger("main")
if (args.isEmpty()) {
Launcher.help()
exitProcess(0)
fun getSize(size: Long): String? {
val kilo = 1024L
val mega = kilo * kilo
val giga = mega * kilo
val tera = giga * kilo
var s = ""
val kb: Double = size.toDouble() / kilo
val mb: Double = kb / kilo
val gb: Double = mb / kilo
val tb: Double = gb / kilo
if (size < kilo) {
s = "$size Bytes"
} else if (size in kilo until mega) {
s = String.format("%.2f", kb) + " KB"
} else if (size in mega until giga) {
s = String.format("%.2f", mb) + " MB"
} else if (size in giga until tera) {
s = String.format("%.2f", gb) + " GB"
} else if (size >= tera) {
s = String.format("%.2f", tb) + " TB"
}
return s
}
}
when (args[0]) {
"crypo.list" -> {
CryptoHelper.listAll()
fun processCommand(inFile: String, info2: Properties) {
FileInputStream(inFile).use { fis ->
info2.load(fis)
}
"crypto.key.parse" -> {
val ba = File(args[1]).readBytes()
val k = CryptoHelper.KeyBox.parse(ba)
if (k is Boolean) {
if (k) {
log.info("File recognized but not parsed")
} else {
log.warn("Unrecognized file " + args[1])
log.warn("CMD=" + info2.getProperty("cmd"))
val kFile = info2.getProperty("file")
when (val cmd = info2.getProperty("cmd")) {
"genrsa" -> {
val kLen = info2.getProperty("rsa.len").toInt()
OpenSslHelper.PK1Key.generate(kLen).apply {
writeTo(kFile)
}
} else {
log.info("Recognized " + k::class)
log.info("RSA key(len=$kLen) written to $kFile")
}
}
"crypto.key.genrsa", "crypto.key.0" -> {
val kLen: Int = args[1].toInt()
val kOut = args[2]
OpenSslHelper.PK1Key.generate(kLen).apply {
writeTo(kOut)
"toPublicKey" -> {
val k = CryptoHelper.KeyBox.parse2(File(kFile).readBytes()) as Array<*>
val bSuccess = k[0] as Boolean
val bType = k[1] as String
var outFile = File(kFile).name + ".pub"
when (k[2]) {
is org.bouncycastle.asn1.pkcs.RSAPrivateKey -> {
val rsa = OpenSslHelper.PK1Key(data = File(kFile).readBytes())
run { //action 1
val hint = "private RSA key -> RSA public key(PEM)"
outFile = File(kFile).name + ".pem.pub"
val rsaPubPEM = rsa.getPublicKey(KeyFormat.PEM).apply {
writeTo(outFile)
log.info("$hint: $kFile => $outFile")
}
}
run { //action 2
val hint = "private RSA key -> RSA public key(DER)"
outFile = File(kFile).name + ".der.pub"
val rsaPubDer = rsa.getPublicKey(KeyFormat.DER).apply {
writeTo(outFile)
log.info("$hint: $kFile => $outFile")
}
}
}
else -> {
}
}
}
log.info("RSA key(len=$kLen) written to $kOut")
}
"crypto.key.1" -> {
//Action-1: private RSA key -> RSA public key(PEM)
val hint = "private RSA key -> RSA public key(PEM)"
val kFile = args[1]
val outFile = args[2]
assert(CryptoHelper.KeyBox.parse(File(kFile).readBytes()) is org.bouncycastle.asn1.pkcs.RSAPrivateKey)
val rsa = OpenSslHelper.PK1Key(data = File(kFile).readBytes())
val rsaPubPEM = rsa.getPublicKey(KeyFormat.PEM).apply {
writeTo(outFile)
"decodePEM" -> {
val hint = "(PEM) --> (DER)"
val outFile = File(kFile).name + ".raw"
val decodeFromPem = CryptoHelper.KeyBox.decodePem(File(kFile).readText())
File(outFile).writeBytes(decodeFromPem)
log.info("$hint: $kFile => $outFile")
}
}
"crypto.key.2" -> {
//Action-2: private RSA key -> RSA public key(DER)
val kFile = args[1]
val outFile = args[2]
assert(CryptoHelper.KeyBox.parse(File(kFile).readBytes()) is org.bouncycastle.asn1.pkcs.RSAPrivateKey)
val rsa = OpenSslHelper.PK1Key(data = File(kFile).readBytes())
val rsaPubDer = rsa.getPublicKey(KeyFormat.DER).apply {
writeTo(outFile)
log.info("RSA pub key(der) written to $outFile")
"toCrt" -> {
val hint = "PK1 RSA PEM ==> CRT"
val outFile = File(kFile).name + ".crt"
CryptoHelper.KeyBox.parseToPk8(kFile)
.toPk1()
.toV1Cert(info2.getProperty("csr.info"))
.writeTo(outFile)
log.info("$hint: $kFile => $outFile")
}
}
"crypto.key.3" -> {
//Action-3: (PEM) --> (DER)
val kFile = args[1]
val outFile = args[2]
val decodeFromPem = CryptoHelper.KeyBox.decodePem(File(kFile).readText())
Files.write(decodeFromPem, File(outFile))
log.info("PEM ($kFile) => raw ($outFile)")
}
"crypto.key.4" -> {
//Action-4:
var hint = "RSA private: PK1 <=> PK8(PEM)"
val kFile = args[1]
val outFile = args[2]
when (val k = CryptoHelper.KeyBox.parse(File(kFile).readBytes())) {
is org.bouncycastle.asn1.pkcs.RSAPrivateKey -> {
hint = "RSA private: PK1 => PK8(PEM)"
val rsa = OpenSslHelper.PK1Key(data = File(kFile).readBytes())
rsa.toPk8(KeyFormat.PEM).writeTo(outFile)
"toCsr" -> {
val hint = "PK1 RSA PEM ==> CSR"
val outFile = File(kFile).name + ".csr"
val inBytes = File(kFile).readBytes()
val k = (CryptoHelper.KeyBox.parse2(inBytes) as Array<*>)[2]
assert(k is org.bouncycastle.asn1.pkcs.RSAPrivateKey) {
"${k!!::class} is not org.bouncycastle.asn1.pkcs.RSAPrivateKey"
}
is java.security.interfaces.RSAPrivateKey -> {
hint = "RSA private: PK8 => PK1(PEM)"
val rsa = OpenSslHelper.PK8RsaKey(data = File(kFile).readBytes())
rsa.toPk1().writeTo(outFile)
OpenSslHelper.PK1Key(KeyFormat.PEM, inBytes).toCsr(info2.getProperty("csr.info")).writeTo(outFile)
log.info("$hint: $kFile => $outFile")
}
"toJks" -> {
val hint = "RSA ==> JKS"
val outFile = File(kFile).name + ".jks"
val pk8 = CryptoHelper.KeyBox.parseToPk8(kFile)
val crt = pk8.toPk1().toV1Cert(info2.getProperty("csr.info"))
OpenSslHelper.Pfx(
name = info2.getProperty("pfx.alias") ?: "androiddebugkey",
thePassword = info2.getProperty("pfx.password") ?: "somepassword"
)
.generate(pk8.toPk1(), crt)
.toJks()
.writeTo(outFile)
log.info("$hint: $kFile => $outFile")
}
"toPk1" -> {
val inBytes = File(kFile).readBytes()
val k = CryptoHelper.KeyBox.parse2(inBytes) as Array<*>
val kType = if ((k[1] as String) == "PEM") KeyFormat.PEM else KeyFormat.DER
val outFile = File(info2.getProperty("file")).name + ".pk1"
assert(k[2] is java.security.interfaces.RSAPrivateKey) {
"${k[2]!!::class} is NOT java.security.interfaces.RSAPrivateKey"
}
else -> {
hint = "RSA private: PK1 <=> PK8(PEM)"
log.warn(hint)
throw IllegalArgumentException("unsupported $k")
val hint = "RSA private: PK8($kType) => PK1(PEM)"
log.info("Running: $hint")
OpenSslHelper.PK8RsaKey(format = kType, data = File(kFile).readBytes())
.toPk1()
.also {
log.info("$kFile -> $outFile")
}
.writeTo(outFile)
}
"toPk8" -> {
val inBytes = File(kFile).readBytes()
val k = CryptoHelper.KeyBox.parse2(inBytes) as Array<*>
val kType = if ((k[1] as String) == "PEM") KeyFormat.PEM else KeyFormat.DER
val outFileStem = File(info2.getProperty("file")).name
assert(k[2] is org.bouncycastle.asn1.pkcs.RSAPrivateKey)
val hint = "RSA private: PK1 => PK8(PEM,DER)"
log.info("Running: $hint")
OpenSslHelper.PK1Key(data = File(kFile).readBytes()).let { rsa ->
rsa.toPk8(KeyFormat.PEM).writeTo("$outFileStem.pem_pk8")
rsa.toPk8(KeyFormat.DER).writeTo("$outFileStem.der_pk8")
}
log.info("$hint: $kFile => $outFileStem.pem_pk8, $outFileStem.der_pk8")
}
else -> {
//pass
}
} //end-of-cmd-mode
}
fun processFile(inFile: String, info2: Properties) {
val preFile = info2.getProperty("file")
info2["file"] = (if (preFile == null) "" else "$preFile,") + File(inFile).canonicalFile.path
info2["propFile"] = File(info2.getProperty("file")).name + ".prop"
val k = CryptoHelper.KeyBox.parse2(File(inFile).readBytes()) as Array<*>
val bSuccess = k[0] as Boolean
val bType = k[1] as String
if (bSuccess) {
info2["fileType"] = bType
info2["fileClazz"] = k[2]!!::class.toString()
log.info("Recognized $bType: " + k[2]!!::class)
if (k[2] is sun.security.x509.X509CertImpl) {
val crt = k[2] as sun.security.x509.X509CertImpl
val crtSubj = (crt.get("x509.info") as sun.security.x509.X509CertInfo).get("subject").toString()
val subj2 = crtSubj
.replace(", ", "/")
.replace("EMAILADDRESS", "emailAddress")
.replace("\\s".toRegex(), "")
info2.setProperty("csr.info", "/$subj2")
}
if (k[2] is sun.security.rsa.RSAPrivateCrtKeyImpl) {
val pk8 = k[2] as sun.security.rsa.RSAPrivateCrtKeyImpl
info2.setProperty("rsa.len", pk8.modulus.bitLength().toString())
info2["rsa.modulus"] = Helper.toHexString(pk8.modulus.toByteArray())
info2["rsa.privateExponent"] = Helper.toHexString(pk8.privateExponent.toByteArray())
info2["rsa.publicExponent"] = Helper.toHexString(pk8.publicExponent.toByteArray())
info2["rsa.primeP"] = Helper.toHexString(pk8.primeP.toByteArray())
info2["rsa.primeQ"] = Helper.toHexString(pk8.primeQ.toByteArray())
}
if (k[2] is org.bouncycastle.asn1.pkcs.RSAPrivateKey) {
val rsa = k[2] as org.bouncycastle.asn1.pkcs.RSAPrivateKey
info2.setProperty("rsa.len", rsa.modulus.bitLength().toString())
info2["rsa.modulus"] = Helper.toHexString(rsa.modulus.toByteArray())
info2["rsa.privateExponent"] = Helper.toHexString(rsa.privateExponent.toByteArray())
info2["rsa.publicExponent"] = Helper.toHexString(rsa.publicExponent.toByteArray())
info2["rsa.primeP"] = Helper.toHexString(rsa.prime1.toByteArray())
info2["rsa.primeQ"] = Helper.toHexString(rsa.prime2.toByteArray())
}
} else {
if (bType == "NA") {
log.warn("Unrecognized file $inFile")
} else {
log.warn("Recognized but not parsed $bType: $inFile")
}
log.info("$hint: $kFile => $outFile")
}
"crypto.key.5" -> {
val hint = "RSA private(PK8): => Public Key(PK8, PEM)"
val kFile = args[1]
val outFile = args[2]
assert(CryptoHelper.KeyBox.parse(File(kFile).readBytes()) is org.bouncycastle.asn1.pkcs.RSAPrivateKey)
val pk8rsa = OpenSslHelper.PK8RsaKey(KeyFormat.PEM, File(kFile).readBytes())
pk8rsa.getPublicKey().writeTo(outFile)
log.info("$hint: $kFile => $outFile")
}
"crypto.key.7" -> {
val hint = "RSA private: PK1 => PK8(DER)"
val kFile = args[1]
val outFile = args[2]
assert(CryptoHelper.KeyBox.parse(File(kFile).readBytes()) is org.bouncycastle.asn1.pkcs.RSAPrivateKey)
val rsa = OpenSslHelper.PK1Key(data = File(kFile).readBytes())
rsa.toPk8(KeyFormat.DER).writeTo(outFile)
log.info("$hint: $kFile => $outFile")
}
"crypto.key.10" -> {
//Action-10:
var hint = ""
val kFile = args[1]
val outFile = args[2]
val inBytes = File(kFile).readBytes()
assert(CryptoHelper.KeyBox.parse(inBytes) is java.security.interfaces.RSAPrivateKey)
val p = PemReader(InputStreamReader(ByteArrayInputStream(File(kFile).readBytes()))).readPemObject()
if (p != null) {//pem
hint = "PK8 RSA: PEM => DER"
OpenSslHelper.PK8RsaKey(KeyFormat.PEM, inBytes).transform(KeyFormat.PEM, KeyFormat.DER).writeTo(outFile)
} else {//der
hint = "PK8 RSA: DER => PEM"
OpenSslHelper.PK8RsaKey(KeyFormat.DER, inBytes).transform(KeyFormat.DER, KeyFormat.PEM).writeTo(outFile)
}
log.info("$hint: $kFile => $outFile")
}
"crypto.key.11" -> {
val hint = "RSA public(PK8): PEM => DER"
val kFile = args[1]
val outFile = args[2]
File(outFile).writeBytes(
CryptoHelper.KeyBox.decodePem(File(kFile).readText())
)
log.info("$hint: $kFile => $outFile")
}
"crypto.key.csr" -> {
//Action-xx:
val hint = "PK1 RSA PEM ==> CSR"
val kFile = args[1]
val outFile = args[2]
val inBytes = File(kFile).readBytes()
assert(CryptoHelper.KeyBox.parse(inBytes) is org.bouncycastle.asn1.pkcs.RSAPrivateKey)
OpenSslHelper.PK1Key(KeyFormat.PEM,inBytes).toCsr().writeTo(outFile)
log.info("$hint: $kFile => $outFile")
}
"crypto.key.crt" -> {
//Action-xx:
val hint = "PK1 RSA PEM ==> CRT"
val kFile = args[1]
val outFile = args[2]
val inBytes = File(kFile).readBytes()
assert(CryptoHelper.KeyBox.parse(inBytes) is org.bouncycastle.asn1.pkcs.RSAPrivateKey)
OpenSslHelper.PK1Key(KeyFormat.PEM,inBytes).toV1Cert().writeTo(outFile)
log.info("$hint: $kFile => $outFile")
}
fun todo(args: Array<String>) {
when (args[0]) {
"crypo.list" -> {
CryptoHelper.listAll()
}
"crypto.key.5" -> {
val hint = "RSA private(PK8): => Public Key(PK8, PEM)"
val kFile = args[1]
val outFile = args[2]
assert((CryptoHelper.KeyBox.parse2(File(kFile).readBytes()) as Array<*>)[2] is org.bouncycastle.asn1.pkcs.RSAPrivateKey)
val pk8rsa = OpenSslHelper.PK8RsaKey(KeyFormat.PEM, File(kFile).readBytes())
pk8rsa.getPublicKey().writeTo(outFile)
log.info("$hint: $kFile => $outFile")
}
"crypto.key.10" -> {
//Action-10:
var hint = "PK8 RSA: PEM <=> DER"
val kFile = args[1]
val outFile = args[2]
val inBytes = File(kFile).readBytes()
assert((CryptoHelper.KeyBox.parse2(inBytes) as Array<*>)[2] is java.security.interfaces.RSAPrivateKey)
val p = PemReader(InputStreamReader(ByteArrayInputStream(File(kFile).readBytes()))).readPemObject()
if (p != null) {//pem
hint = "PK8 RSA: PEM => DER"
OpenSslHelper.PK8RsaKey(KeyFormat.PEM, inBytes).transform(KeyFormat.PEM, KeyFormat.DER)
.writeTo(outFile)
} else {//der
hint = "PK8 RSA: DER => PEM"
OpenSslHelper.PK8RsaKey(KeyFormat.DER, inBytes).transform(KeyFormat.DER, KeyFormat.PEM)
.writeTo(outFile)
}
log.info("$hint: $kFile => $outFile")
}
"crypto.key.11" -> {
val hint = "RSA public(PK8): PEM => DER"
val kFile = args[1]
val outFile = args[2]
File(outFile).writeBytes(
CryptoHelper.KeyBox.decodePem(File(kFile).readText())
)
log.info("$hint: $kFile => $outFile")
}
"crypto.key.22" -> {
//Action-xx:
val hint = "CRT ==> JKS"
val kFile = args[1]
val crtFile = args[2]
val outFile = args[3]
assert((CryptoHelper.KeyBox.parse2(File(crtFile).readBytes()) as Array<*>)[2] is Certificate)
val envPassword = System.getProperty("password") ?: "secretpassword"
val envAlias = System.getProperty("alias") ?: "someUnknownAlias"
val crt = OpenSslHelper.Crt(File(crtFile).readBytes())
val rsa = OpenSslHelper.PK1Key(KeyFormat.PEM, File(kFile).readBytes())
OpenSslHelper.Pfx(name = envAlias, thePassword = envPassword).generate(rsa, crt).toJks()
.writeTo(outFile)
log.info("$hint: $kFile => $outFile")
}
"crypto.key.jks" -> {
//Action-xx:
val hint = "Generate JKS"
val keypass = args[1]
val storepass = args[2]
val alias = args[3]
val outFile = args[4]
OpenSslHelper.Jks.generate(keypass, storepass, alias, null, outFile)
log.info("$hint: ==> $outFile")
}
"crypto.key.23" -> {
//Action-xx:
val hint = "PK1 ==> JKS"
val kFile = args[1]
val outFile = args[2]
val rsa = OpenSslHelper.PK1Key(KeyFormat.PEM, File(kFile).readBytes())
val crt = rsa.toV1Cert()
OpenSslHelper.Pfx(name = "androiddebugkey", thePassword = "somepassword").generate(rsa, crt).toJks()
.writeTo(outFile)
log.info("$hint: $kFile => $outFile")
}
"crypto.key.xx" -> {
//Action-xx:
val hint = ""
val kFile = args[1]
val k = CryptoHelper.KeyBox.parse2(File(kFile).readBytes()) as Array<*>
println(k[2]!!.toString())
val crt = k[2] as sun.security.x509.X509CertImpl
log.info("type=" + crt.type + ", name=" + crt.name)
for (item in crt.elements) {
log.info("# $item")
}
val crtInfo = crt.get("x509.info") as sun.security.x509.X509CertInfo
for (item in crtInfo.elements) {
log.info("## $item")
}
log.info("subject=>")
log.info(crtInfo.get("subject").toString())
log.info("issuer=>")
log.info(crtInfo.get("issuer").toString())
log.info("$hint: $kFile => ")
}
else -> {
Launcher.help()
exitProcess(1)
}
}
"crypto.key.22" -> {
//Action-xx:
val hint = "CRT ==> JKS"
val kFile = args[1]
val outFile = args[2]
val inBytes = File(kFile).readBytes()
assert(CryptoHelper.KeyBox.parse(inBytes) is org.bouncycastle.asn1.pkcs.RSAPrivateKey)
OpenSslHelper.PK1Key(KeyFormat.PEM,inBytes).toV1Cert().writeTo(outFile)
log.info("$hint: $kFile => $outFile")
}
}
fun main(args: Array<String>) {
val log = LoggerFactory.getLogger("main")
val allSupportedCommands =
listOf("genrsa", "toPublicKey", "decodePEM", "toPk8", "toPk1", "toJks", "toCsr", "toCrt").toString()
val info2 = Properties().apply {
this.setProperty("all_cmds", allSupportedCommands)
this["available_cmds"] = this.getProperty("all_cmds")
this["cmd"] = ""
this.setProperty(
"csr.info", "/C=CN/ST=Shanghai/L=Shanghai/O=XXX/OU=infra/CN=gerrit/emailAddress=webmaster@XX.com"
)
this.setProperty("pfx.alias", "androiddebugkey")
this.setProperty("pfx.password", "somepassword")
}
if (args.isEmpty()) {
info2.setProperty("rsa.len", 4096.toString())
info2["file"] = "k"
info2["propFile"] = "run.prop"
FileOutputStream(info2.getProperty("propFile")).use { fos ->
info2.store(fos, null)
log.info("Writing to " + info2.getProperty("propFile"))
}
"crypto.key.xx" -> {
//Action-xx:
val hint = ""
val kFile = args[1]
val outFile = args[2]
File(outFile).writeBytes(
CryptoHelper.KeyBox.decodePem(File(kFile).readText())
)
log.info("$hint: $kFile => $outFile")
exitProcess(0)
}
if (args.size == 1 && File(args[0]).exists() && args[0].endsWith(".prop")) { //cmd mode
Launcher().processCommand(args[0], info2)
} else { // file mode
args.forEachIndexed { index, s ->
log.warn("[${index + 1}/${args.size}] Processing $s ...")
Launcher().processFile(s, info2)
}
else -> {
Launcher.help()
exitProcess(1)
FileOutputStream(info2.getProperty("propFile")).use { fos ->
info2.setProperty("all_cmds", allSupportedCommands)
info2.store(fos, null)
log.info("Writing to " + info2.getProperty("propFile"))
}
}
return
}
}

@ -114,14 +114,14 @@ class OpenSslHelper {
}
}
fun toV1Cert(): Crt {
fun toV1Cert(info: String? = null): Crt {
//full command:
// openssl x509 -req -in 2017key.csr -signkey 2017key.rsa.pem -out theCert.crt -days 180
//send RSA key as input stream:
// openssl x509 -req -in 2017key.csr -signkey - -out theCert.crt -days 180
//send RSA key as input stream, crt as output stream:
// openssl x509 -req -in 2017key.csr -signkey - -days 180
val csr = this.toCsr()
val csr = this.toCsr(info)
val tmpFile = File.createTempFile("pk1.", ".csr")
tmpFile.writeBytes(csr.data)
tmpFile.deleteOnExit()
@ -148,6 +148,12 @@ class OpenSslHelper {
log.info("generateRSA:stderr: ${String(ret[1])}")
return PK1Key(format = KeyFormat.PEM, data = ret[0])
}
fun generate(keyLength: Int, password: String): PK1Key {
val ret = Helper.powerRun("openssl genrsa -aes256 -passout pass:$password $keyLength", null)
log.info("generateRSA:stderr: ${String(ret[1])}")
return PK1Key(format = KeyFormat.PEM, data = ret[0])
}
}
}
@ -166,12 +172,16 @@ class OpenSslHelper {
openssl rsa -in - -out -
*/
fun toPk1(): PK1Key {
if (this.format != KeyFormat.PEM) {
throw IllegalArgumentException("Only pk8+pem can be converted to RSA")
}
val transformed =
if (this.format != KeyFormat.PEM) {
log.warn("Only pk8+pem can be converted to RSA, transforming ...")
this.transform(KeyFormat.DER, KeyFormat.PEM)
} else {
this
}
val ret = Helper.powerRun2(
"openssl rsa -in $stdin",
ByteArrayInputStream(data)
ByteArrayInputStream(transformed.data)
)
if (ret[0] as Boolean) {
log.info("toRsaPrivate:error: ${String(ret[2] as ByteArray)}")
@ -241,7 +251,7 @@ class OpenSslHelper {
class Csr(override val name: String = "CSR", override val data: ByteArray = byteArrayOf()) : IKey
class Jks(override val name: String = "Java Keystore", override val data: ByteArray = byteArrayOf()) : IKey {
//keytool -list -v -deststorepass $(thePassword) -keystore $(jks_file)
fun check(passWord: String = "somepassword") {
fun check(passWord: String = "secretpassword") {
val tmpFile = File.createTempFile("tmp.", ".jks").apply { this.deleteOnExit() }
tmpFile.writeBytes(this.data)
val ret = Helper.powerRun2(
@ -257,18 +267,47 @@ class OpenSslHelper {
throw RuntimeException()
}
}
companion object {
fun generate(keyPass: String, storePass: String, alias: String, dname: String?, outFile: String) {
//val cmd = "keytool -genkey -noprompt -alias $alias -dname \"$defaultInfo\" -keystore $outFile -storepass $storePass -keypass $keyPass"
val defaultInfo =
dname ?: "CN=Unknown, OU=Unknown, O=Unknown Software Company, L=Unknown, ST=Unknown, C=Unknown"
val cmd = CommandLine.parse("keytool -genkey -noprompt -keyalg RSA").apply {
addArgument("-alias").addArgument(alias)
addArgument("-dname").addArgument(defaultInfo, false)
addArgument("-keystore").addArgument(outFile)
addArgument("-storepass").addArgument(storePass)
addArgument("-keypass").addArgument(keyPass)
}
val ret = Helper.powerRun3(cmd, null)
if (ret[0] as Boolean) {
log.info("Jks.gen:stdout: ${String(ret[1] as ByteArray)}")
log.info("Jks.gen:error: ${String(ret[2] as ByteArray)}")
} else {
log.error("Jks.gen:stdout: " + String(ret[1] as ByteArray))
log.error("Jks.gen:stderr: " + String(ret[2] as ByteArray))
throw RuntimeException()
}
}
}
}
class Crt(override val data: ByteArray = byteArrayOf(), override val name: String = "crt") : IKey {
//Result: trustedCertEntry
//keytool -importcert -file 2017key.crt -deststorepass somepassword -srcstorepass somepassword -keystore 2017key.2.jks
fun toJks(paramSrcPass: String = "somepassword", paramDstPass: String = "somepassword"): Jks {
//keytool -importcert -file 2017key.crt -deststorepass secretpassword -srcstorepass secretpassword -keystore 2017key.2.jks
fun toJks(
paramSrcPass: String = "secretpassword",
paramDstPass: String = "secretpassword",
alias: String = "awesomeKey"
): Jks {
val crtFile = File.createTempFile("tmp.", ".crt").apply { this.deleteOnExit() }
crtFile.writeBytes(this.data)
val outFile = File.createTempFile("tmp.", ".jks").apply { this.delete() }
val ret = Helper.powerRun2(
"keytool -importcert -file ${crtFile.path}" +
" -deststorepass $paramDstPass -srcstorepass $paramSrcPass " +
" -alias $alias " +
" -keystore ${outFile.path}",
ByteArrayInputStream("yes\n".toByteArray())
)
@ -292,10 +331,10 @@ class OpenSslHelper {
class Pfx(
override val name: String = "androiddebugkey",
var thePassword: String = "somepassword",
var thePassword: String = "secretpassword",
override var data: ByteArray = byteArrayOf()
) : IKey {
fun generate(pk1: PK1Key, crt: Crt) {
fun generate(pk1: PK1Key, crt: Crt): Pfx {
val pk1File = File.createTempFile("tmp.", ".file").apply { this.deleteOnExit() }
pk1File.writeBytes(pk1.data)
@ -317,6 +356,7 @@ class OpenSslHelper {
log.error("stderr: " + String(ret[2] as ByteArray))
throw RuntimeException()
}
return this
}
//keytool -importkeystore -deststorepass $(thePassword) -destkeystore $(jks_file) -srckeystore $(pfx_cert) -srcstoretype PKCS12 -srcstorepass $(thePassword)
@ -348,7 +388,7 @@ class OpenSslHelper {
private val log = LoggerFactory.getLogger(OpenSslHelper::class.java)
val stdin = if (System.getProperty("os.name").contains("Mac")) "/dev/stdin" else "-"
fun toPfx(password: String = "somepassword", keyName: String = "androiddebugkey", pk1: PK1Key, crt: Crt) {
fun toPfx(password: String = "secretpassword", keyName: String = "androiddebugkey", pk1: PK1Key, crt: Crt) {
val pk1File = File.createTempFile("tmp.", ".file").apply { this.deleteOnExit() }
pk1File.writeBytes(pk1.data)

Loading…
Cancel
Save