unify helpers and remove codacy
parent
ea73a704b3
commit
30a5a0cbad
@ -1,3 +0,0 @@
|
||||
---
|
||||
exclude_paths:
|
||||
- 'aosp/**'
|
@ -0,0 +1,93 @@
|
||||
package cfig.helper
|
||||
|
||||
import cfig.io.Struct3
|
||||
import com.google.common.math.BigIntegerMath
|
||||
import org.apache.commons.codec.binary.Hex
|
||||
import org.bouncycastle.util.io.pem.PemReader
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.InputStream
|
||||
import java.io.InputStreamReader
|
||||
import java.math.BigInteger
|
||||
import java.math.RoundingMode
|
||||
import java.security.Security
|
||||
|
||||
class KeyHelper {
|
||||
companion object {
|
||||
private val log = LoggerFactory.getLogger(KeyHelper::class.java)
|
||||
|
||||
@Throws(IllegalArgumentException::class)
|
||||
fun parsePemPubkey(inputStream: InputStream): org.bouncycastle.asn1.pkcs.RSAPublicKey {
|
||||
val p = PemReader(InputStreamReader(inputStream)).readPemObject()
|
||||
if ("RSA PUBLIC KEY" != p.type) {
|
||||
throw IllegalArgumentException("input is not valid 'RSA PUBLIC KEY'")
|
||||
}
|
||||
return org.bouncycastle.asn1.pkcs.RSAPublicKey.getInstance(p.content)
|
||||
}
|
||||
|
||||
@Throws(IllegalArgumentException::class)
|
||||
fun parsePemPrivateKeyBC(inputStream: InputStream): org.bouncycastle.asn1.pkcs.RSAPrivateKey {
|
||||
val p = PemReader(InputStreamReader(inputStream)).readPemObject()
|
||||
if ("RSA PRIVATE KEY" != p.type) {
|
||||
throw IllegalArgumentException("input is not valid 'RSA PRIVATE KEY'")
|
||||
}
|
||||
return org.bouncycastle.asn1.pkcs.RSAPrivateKey.getInstance(p.content)
|
||||
}
|
||||
|
||||
// fun parsePemPrivateKey(inputStream: InputStream): java.security.PrivateKey {
|
||||
// val rsa = BC.parsePemPrivateKeyBC(inputStream)
|
||||
// return generateRsaPrivateKey(rsa.modulus, rsa.privateExponent)
|
||||
// }
|
||||
|
||||
|
||||
/*
|
||||
read RSA private key
|
||||
assert exp == 65537
|
||||
num_bits = log2(modulus)
|
||||
|
||||
@return: AvbRSAPublicKeyHeader formatted bytearray
|
||||
https://android.googlesource.com/platform/external/avb/+/master/libavb/avb_crypto.h#158
|
||||
from avbtool::encode_rsa_key()
|
||||
*/
|
||||
fun encodeRSAkey(key: ByteArray): ByteArray {
|
||||
val rsa = parsePemPrivateKeyBC(ByteArrayInputStream(key))
|
||||
assert(65537.toBigInteger() == rsa.publicExponent)
|
||||
val numBits: Int = BigIntegerMath.log2(rsa.modulus, RoundingMode.CEILING)
|
||||
log.debug("modulus: " + rsa.modulus)
|
||||
log.debug("numBits: $numBits")
|
||||
val b = BigInteger.valueOf(2).pow(32)
|
||||
val n0inv = (b - rsa.modulus.modInverse(b)).toLong()
|
||||
log.debug("n0inv = $n0inv")
|
||||
val r = BigInteger.valueOf(2).pow(numBits)
|
||||
val rrModn = (r * r).mod(rsa.modulus)
|
||||
log.debug("BB: " + numBits / 8 + ", mod_len: " + rsa.modulus.toByteArray().size + ", rrmodn = " + rrModn.toByteArray().size)
|
||||
val unsignedModulo = rsa.modulus.toByteArray().sliceArray(1..numBits / 8) //remove sign byte
|
||||
log.debug("unsigned modulo: " + Hex.encodeHexString(unsignedModulo))
|
||||
val ret = Struct3("!II${numBits / 8}b${numBits / 8}b").pack(
|
||||
numBits,
|
||||
n0inv,
|
||||
unsignedModulo,
|
||||
rrModn.toByteArray())
|
||||
log.debug("rrmodn: " + Hex.encodeHexString(rrModn.toByteArray()))
|
||||
log.debug("RSA: " + Hex.encodeHexString(ret))
|
||||
return ret
|
||||
}
|
||||
|
||||
fun listAll() {
|
||||
Security.getProviders().forEach {
|
||||
val sb = StringBuilder("Provider: " + it.name + "{")
|
||||
it.stringPropertyNames().forEach { key ->
|
||||
sb.append(" (k=" + key + ",v=" + it.getProperty(key) + "), ")
|
||||
}
|
||||
sb.append("}")
|
||||
log.info(sb.toString())
|
||||
}
|
||||
|
||||
var i = 0
|
||||
for (item in Security.getAlgorithms("Cipher")) {
|
||||
log.info("Cipher: $i -> $item")
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,187 @@
|
||||
package cfig.helper
|
||||
|
||||
import org.apache.commons.codec.binary.Hex
|
||||
import org.apache.commons.exec.CommandLine
|
||||
import org.apache.commons.exec.DefaultExecutor
|
||||
import org.apache.commons.exec.ExecuteException
|
||||
import org.apache.commons.exec.PumpStreamHandler
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.math.BigInteger
|
||||
import java.security.*
|
||||
import java.security.spec.PKCS8EncodedKeySpec
|
||||
import java.security.spec.RSAPrivateKeySpec
|
||||
import java.security.spec.RSAPublicKeySpec
|
||||
import java.security.spec.X509EncodedKeySpec
|
||||
import java.util.*
|
||||
import javax.crypto.Cipher
|
||||
|
||||
class KeyHelper2 {
|
||||
companion object {
|
||||
private val log = LoggerFactory.getLogger(KeyHelper2::class.java)
|
||||
|
||||
fun parseRsaPk8(inputData: ByteArray): java.security.PrivateKey {
|
||||
val spec = PKCS8EncodedKeySpec(inputData)
|
||||
return KeyFactory.getInstance("RSA").generatePrivate(spec)
|
||||
}
|
||||
|
||||
fun parseRsaKey(keyText: String): PrivateKey {
|
||||
val publicKeyPEM = keyText
|
||||
.replace("-----BEGIN RSA PRIVATE KEY-----", "")
|
||||
.replace(System.lineSeparator().toRegex(), "")
|
||||
.replace("\n", "")
|
||||
.replace("\r", "")
|
||||
.replace("-----END RSA PRIVATE KEY-----", "")
|
||||
log.warn("trimmed key")
|
||||
log.warn(publicKeyPEM)
|
||||
val encoded: ByteArray = Base64.getDecoder().decode(publicKeyPEM)
|
||||
val keySpec = X509EncodedKeySpec(encoded)
|
||||
return KeyFactory.getInstance("RSA").generatePrivate(keySpec)
|
||||
}
|
||||
|
||||
fun parsePemPubkey(keyText: String): java.security.interfaces.RSAPublicKey {
|
||||
val publicKeyPEM = keyText
|
||||
.replace("-----BEGIN PUBLIC KEY-----", "")
|
||||
.replace(System.lineSeparator().toRegex(), "")
|
||||
.replace("\n", "")
|
||||
.replace("\r", "")
|
||||
.replace("-----END PUBLIC KEY-----", "")
|
||||
val encoded: ByteArray = Base64.getDecoder().decode(publicKeyPEM)
|
||||
val keySpec = X509EncodedKeySpec(encoded)
|
||||
return KeyFactory.getInstance("RSA").generatePublic(keySpec) as java.security.interfaces.RSAPublicKey
|
||||
}
|
||||
|
||||
|
||||
fun parsePemPubCert(keyText: String) {
|
||||
val publicKeyPEM = keyText
|
||||
.replace("-----BEGIN CERTIFICATE-----", "")
|
||||
.replace(System.lineSeparator().toRegex(), "")
|
||||
.replace("\n", "")
|
||||
.replace("\r", "")
|
||||
.replace("-----END CERTIFICATE-----", "")
|
||||
val encoded: ByteArray = Base64.getDecoder().decode(publicKeyPEM)
|
||||
val keySpec = X509EncodedKeySpec(encoded)
|
||||
// return KeyFactory.getInstance("RSA").generatePublic(keySpec) as java.security.interfaces.RSAPublicKey
|
||||
}
|
||||
|
||||
/*
|
||||
in: modulus, expo
|
||||
out: PublicKey
|
||||
*/
|
||||
fun generateRsaPublicKey(modulus: BigInteger, publicExponent: BigInteger): java.security.PublicKey {
|
||||
return KeyFactory.getInstance("RSA").generatePublic(RSAPublicKeySpec(modulus, publicExponent))
|
||||
}
|
||||
|
||||
/*
|
||||
in: modulus, expo
|
||||
out: PrivateKey
|
||||
*/
|
||||
fun generateRsaPrivateKey(modulus: BigInteger, privateExponent: BigInteger): java.security.PrivateKey {
|
||||
return KeyFactory.getInstance("RSA").generatePrivate(RSAPrivateKeySpec(modulus, privateExponent))
|
||||
}
|
||||
|
||||
//inspired by
|
||||
// https://stackoverflow.com/questions/40242391/how-can-i-sign-a-raw-message-without-first-hashing-it-in-bouncy-castle
|
||||
// "specifying Cipher.ENCRYPT mode or Cipher.DECRYPT mode doesn't make a difference;
|
||||
// both simply perform modular exponentiation"
|
||||
fun rawSign(privk: java.security.PrivateKey, data: ByteArray): ByteArray {
|
||||
return Cipher.getInstance("RSA/ECB/NoPadding").let { cipher ->
|
||||
cipher.init(Cipher.ENCRYPT_MODE, privk)
|
||||
cipher.update(data)
|
||||
cipher.doFinal()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun rawSignOpenSsl(keyPath: String, data: ByteArray): ByteArray {
|
||||
log.debug("raw input: " + Hex.encodeHexString(data))
|
||||
log.debug("Raw sign data size = ${data.size}, key = $keyPath")
|
||||
var ret = byteArrayOf()
|
||||
val exe = DefaultExecutor()
|
||||
val stdin = ByteArrayInputStream(data)
|
||||
val stdout = ByteArrayOutputStream()
|
||||
val stderr = ByteArrayOutputStream()
|
||||
exe.streamHandler = PumpStreamHandler(stdout, stderr, stdin)
|
||||
try {
|
||||
exe.execute(CommandLine.parse("openssl rsautl -sign -inkey $keyPath -raw"))
|
||||
ret = stdout.toByteArray()
|
||||
log.debug("Raw signature size = " + ret.size)
|
||||
} catch (e: ExecuteException) {
|
||||
log.error("Execute error")
|
||||
} finally {
|
||||
log.debug("OUT: " + Hex.encodeHexString(stdout.toByteArray()))
|
||||
log.debug("ERR: " + String(stderr.toByteArray()))
|
||||
}
|
||||
|
||||
if (ret.isEmpty()) throw RuntimeException("raw sign failed")
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
fun pyAlg2java(alg: String): String {
|
||||
return when (alg) {
|
||||
"sha1" -> "sha-1"
|
||||
"sha224" -> "sha-224"
|
||||
"sha256" -> "sha-256"
|
||||
"sha384" -> "sha-384"
|
||||
"sha512" -> "sha-512"
|
||||
else -> throw IllegalArgumentException("unknown algorithm: [$alg]")
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
openssl dgst -sha256 <file>
|
||||
*/
|
||||
fun sha256(inData: ByteArray): ByteArray {
|
||||
return MessageDigest.getInstance("SHA-256").digest(inData)
|
||||
}
|
||||
|
||||
fun rsa(inData: ByteArray, inKey: java.security.PrivateKey): ByteArray {
|
||||
return Cipher.getInstance("RSA").let {
|
||||
it.init(Cipher.ENCRYPT_MODE, inKey)
|
||||
it.doFinal(inData)
|
||||
}
|
||||
}
|
||||
|
||||
fun sha256rsa(inData: ByteArray, inKey: java.security.PrivateKey): ByteArray {
|
||||
return rsa(sha256(inData), inKey)
|
||||
}
|
||||
|
||||
fun sign(inData: ByteArray, privateKey: PrivateKey): String {
|
||||
val signature = Signature.getInstance("SHA256withRSA").let {
|
||||
it.initSign(privateKey)
|
||||
it.update(inData)
|
||||
it.sign()
|
||||
}
|
||||
return Base64.getEncoder().encodeToString(signature)
|
||||
}
|
||||
|
||||
fun verify(inData: ByteArray, signature: ByteArray, pubKey: PublicKey): Boolean {
|
||||
return Signature.getInstance("SHA256withRSA").let {
|
||||
it.initVerify(pubKey)
|
||||
it.update(inData)
|
||||
it.verify(signature)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun verify(inData: ByteArray, base64Signature: String, pubKey: PublicKey): Boolean {
|
||||
val signatureBytes = Base64.getDecoder().decode(base64Signature)
|
||||
return Signature.getInstance("SHA256withRSA").let {
|
||||
it.initVerify(pubKey)
|
||||
it.update(inData)
|
||||
it.verify(signatureBytes)
|
||||
}
|
||||
}
|
||||
|
||||
fun verify2(inData: ByteArray, encrypedHash: ByteArray, inKey: java.security.PublicKey): Boolean {
|
||||
val calcHash = sha256(inData)
|
||||
val decrypedHash = Cipher.getInstance("RSA").let {
|
||||
it.init(Cipher.DECRYPT_MODE, inKey)
|
||||
it.doFinal(encrypedHash)
|
||||
}
|
||||
return calcHash.contentEquals(decrypedHash)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,341 @@
|
||||
package cfig.helper
|
||||
|
||||
import org.apache.commons.exec.CommandLine
|
||||
import org.bouncycastle.util.encoders.Hex
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.lang.RuntimeException
|
||||
import java.util.*
|
||||
|
||||
class OpenSslHelper {
|
||||
enum class KeyFormat {
|
||||
PEM, //header + metadata + base64 der
|
||||
DER // der format
|
||||
}
|
||||
|
||||
interface IKey {
|
||||
val name: String
|
||||
val data: ByteArray
|
||||
fun writeTo(fileName: String) {
|
||||
FileOutputStream(fileName, false).use {
|
||||
it.write(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PK1Key(val format: KeyFormat = KeyFormat.PEM,
|
||||
override val data: ByteArray = byteArrayOf(),
|
||||
override val name: String = "RSA Private") : IKey {
|
||||
/*
|
||||
PEM private key -> PEM/DER public key
|
||||
*/
|
||||
fun getPublicKey(pubKeyFormat: KeyFormat): PK1PubKey {
|
||||
if (format != KeyFormat.PEM) {
|
||||
throw IllegalArgumentException("can not handle $format private key")
|
||||
}
|
||||
val ret = Helper.powerRun("openssl rsa -in - -pubout -outform ${pubKeyFormat.name}",
|
||||
ByteArrayInputStream(data))
|
||||
log.info("privateToPublic:stderr: ${String(ret[1])}")
|
||||
return PK1PubKey(format = pubKeyFormat, data = ret[0])
|
||||
}
|
||||
|
||||
/*
|
||||
file based:
|
||||
openssl rsa -in private.pem -pubout -out public.pem
|
||||
stream based:
|
||||
openssl rsa -in - -pubout
|
||||
*/
|
||||
fun getPk8PublicKey(): Pk8PubKey {
|
||||
if (this.format != KeyFormat.PEM) {
|
||||
throw java.lang.IllegalArgumentException("Only PEM key is supported")
|
||||
}
|
||||
val ret = Helper.powerRun2("openssl rsa -in - -pubout",
|
||||
ByteArrayInputStream(data))
|
||||
if (ret[0] as Boolean) {
|
||||
log.info("getPk8PublicKey:error: ${String(ret[2] as ByteArray)}")
|
||||
return Pk8PubKey(KeyFormat.PEM, ret[1] as ByteArray)
|
||||
} else {
|
||||
log.error("stdout: " + String(ret[1] as ByteArray))
|
||||
log.error("stderr: " + String(ret[2] as ByteArray))
|
||||
throw RuntimeException()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
file based:
|
||||
openssl pkcs8 -nocrypt -in $(rsa_key) -topk8 -outform DER -out $(pk8_key)
|
||||
stream based:
|
||||
openssl pkcs8 -nocrypt -in - -topk8 -outform DER
|
||||
*/
|
||||
fun toPk8(pk8Format: KeyFormat): PK8RsaKey {
|
||||
val ret = Helper.powerRun("openssl pkcs8 -nocrypt -in - -topk8 -outform ${pk8Format.name}",
|
||||
ByteArrayInputStream(data))
|
||||
log.info("toPk8Private:stderr: ${String(ret[1])}")
|
||||
return PK8RsaKey(format = pk8Format, data = ret[0])
|
||||
}
|
||||
|
||||
fun toCsr(): Csr {
|
||||
val info = "/C=CN/ST=Shanghai/L=Shanghai/O=XXX/OU=infra/CN=gerrit/emailAddress=webmaster@XX.com"
|
||||
val cmdLine = CommandLine.parse("openssl req -new -key - -subj").apply {
|
||||
this.addArgument("$info", true)
|
||||
}
|
||||
val ret = Helper.powerRun3(cmdLine, ByteArrayInputStream(data))
|
||||
if (ret[0] as Boolean) {
|
||||
log.info("toCsr:error: ${String(ret[2] as ByteArray)}")
|
||||
return Csr(data = ret[1] as ByteArray)
|
||||
} else {
|
||||
log.error("stdout: " + String(ret[1] as ByteArray))
|
||||
log.error("stderr: " + String(ret[2] as ByteArray))
|
||||
throw RuntimeException()
|
||||
}
|
||||
}
|
||||
|
||||
fun toV1Cert(): 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 tmpFile = File.createTempFile("pk1.", ".csr")
|
||||
tmpFile.writeBytes(csr.data)
|
||||
tmpFile.deleteOnExit()
|
||||
val ret = Helper.powerRun2("openssl x509 -req -in ${tmpFile.path} -signkey - -days 180",
|
||||
ByteArrayInputStream(data))
|
||||
if (ret[0] as Boolean) {
|
||||
log.info("toCrt:error: ${String(ret[2] as ByteArray)}")
|
||||
return Crt(ret[1] as ByteArray)
|
||||
} else {
|
||||
log.error("stdout: " + String(ret[1] as ByteArray))
|
||||
log.error("stderr: " + String(ret[2] as ByteArray))
|
||||
throw RuntimeException()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
/*
|
||||
-> PEM RSA private key
|
||||
*/
|
||||
fun generate(keyLength: Int): PK1Key {
|
||||
val ret = Helper.powerRun("openssl genrsa $keyLength", null)
|
||||
log.info("generateRSA:stderr: ${String(ret[1])}")
|
||||
return PK1Key(format = KeyFormat.PEM, data = ret[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PK8RsaKey(val format: KeyFormat = KeyFormat.PEM,
|
||||
override val data: ByteArray = byteArrayOf(),
|
||||
override val name: String = "PK8 Private") : IKey {
|
||||
|
||||
/*
|
||||
file based:
|
||||
openssl pkcs8 -nocrypt -in $(pk8_key) -inform DER -out $(rsa_key).converted.tmp
|
||||
openssl rsa -in $(rsa_key).converted.tmp -out $(rsa_key).converted
|
||||
stream based:
|
||||
openssl pkcs8 -nocrypt -in - -inform DER
|
||||
openssl rsa -in - -out -
|
||||
*/
|
||||
fun toPk1(): PK1Key {
|
||||
if (this.format != KeyFormat.PEM) {
|
||||
throw IllegalArgumentException("Only pk8+pem can be converted to RSA")
|
||||
}
|
||||
val ret = Helper.powerRun2("openssl rsa -in -",
|
||||
ByteArrayInputStream(data))
|
||||
if (ret[0] as Boolean) {
|
||||
log.info("toRsaPrivate:error: ${String(ret[2] as ByteArray)}")
|
||||
return PK1Key(KeyFormat.PEM, ret[1] as ByteArray)
|
||||
} else {
|
||||
log.error("stdout: " + String(ret[1] as ByteArray))
|
||||
log.error("stderr: " + String(ret[2] as ByteArray))
|
||||
throw RuntimeException()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
openssl pkcs8 -nocrypt -in - -inform DER
|
||||
*/
|
||||
fun transform(inFormat: KeyFormat, outFormat: KeyFormat): PK8RsaKey {
|
||||
val ret = Helper.powerRun2("openssl pkcs8 -nocrypt -in - -inform ${inFormat.name} -outform ${outFormat.name}",
|
||||
ByteArrayInputStream(data))
|
||||
if (ret[0] as Boolean) {
|
||||
log.info("transform:error: ${String(ret[2] as ByteArray)}")
|
||||
return PK8RsaKey(data = ret[1] as ByteArray)
|
||||
} else {
|
||||
log.error("stdout: " + String(ret[1] as ByteArray))
|
||||
log.error("stderr: " + String(ret[2] as ByteArray))
|
||||
throw IllegalArgumentException()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
file based:
|
||||
openssl rsa -in pkcs8.pem -pubout -out public_pkcs8.pem
|
||||
stream based:
|
||||
openssl rsa -in - -pubout
|
||||
*/
|
||||
fun getPublicKey(): Pk8PubKey {
|
||||
if (this.format != KeyFormat.PEM) {
|
||||
throw java.lang.IllegalArgumentException("Only PEM key is supported")
|
||||
}
|
||||
val ret = Helper.powerRun2("openssl rsa -in - -pubout",
|
||||
ByteArrayInputStream(data))
|
||||
if (ret[0] as Boolean) {
|
||||
log.info("getPublicKey:error: ${String(ret[2] as ByteArray)}")
|
||||
return Pk8PubKey(KeyFormat.PEM, ret[1] as ByteArray)
|
||||
} else {
|
||||
log.error("stdout: " + String(ret[1] as ByteArray))
|
||||
log.error("stderr: " + String(ret[2] as ByteArray))
|
||||
throw RuntimeException()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PK1PubKey(
|
||||
val format: KeyFormat = KeyFormat.PEM,
|
||||
override val data: ByteArray = byteArrayOf(),
|
||||
override val name: String = "RSA Public"
|
||||
) : IKey
|
||||
|
||||
class Pk8PubKey(
|
||||
val format: KeyFormat = KeyFormat.PEM,
|
||||
override val data: ByteArray = byteArrayOf(),
|
||||
override val name: String = "Pk8 Public"
|
||||
) : IKey
|
||||
|
||||
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") {
|
||||
val tmpFile = File.createTempFile("tmp.", ".jks").apply { this.deleteOnExit() }
|
||||
tmpFile.writeBytes(this.data)
|
||||
val ret = Helper.powerRun2("keytool -list -v -deststorepass $passWord -keystore $tmpFile",
|
||||
null)
|
||||
if (ret[0] as Boolean) {
|
||||
log.info("Jks.check:stdout: ${String(ret[1] as ByteArray)}")
|
||||
log.info("Jks.check:error: ${String(ret[2] as ByteArray)}")
|
||||
} else {
|
||||
log.error("stdout: " + String(ret[1] as ByteArray))
|
||||
log.error("stderr: " + String(ret[2] as ByteArray))
|
||||
throw RuntimeException()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Crt(val data: ByteArray = byteArrayOf()) {
|
||||
//Result: trustedCertEntry
|
||||
//keytool -importcert -file 2017key.crt -deststorepass somepassword -srcstorepass somepassword -keystore 2017key.2.jks
|
||||
fun toJks(paramSrcPass: String = "somepassword", paramDstPass: String = "somepassword"): 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 " +
|
||||
" -keystore ${outFile.path}",
|
||||
ByteArrayInputStream("yes\n".toByteArray()))
|
||||
if (ret[0] as Boolean) {
|
||||
log.info("toJks:error: ${String(ret[2] as ByteArray)}")
|
||||
log.info("toJks:stdout: ${String(ret[1] as ByteArray)}")
|
||||
} else {
|
||||
log.error("stdout: " + String(ret[1] as ByteArray))
|
||||
log.error("stderr: " + String(ret[2] as ByteArray))
|
||||
throw RuntimeException()
|
||||
}
|
||||
|
||||
if (!outFile.exists()) {
|
||||
throw RuntimeException()
|
||||
}
|
||||
val outData = outFile.readBytes()
|
||||
outFile.delete()
|
||||
return Jks(data = outData)
|
||||
}
|
||||
}
|
||||
|
||||
class Pfx(override val name: String = "androiddebugkey",
|
||||
var thePassword: String = "somepassword",
|
||||
override var data: ByteArray = byteArrayOf()) : IKey {
|
||||
fun generate(pk1: PK1Key, crt: Crt) {
|
||||
val pk1File = File.createTempFile("tmp.", ".file").apply { this.deleteOnExit() }
|
||||
pk1File.writeBytes(pk1.data)
|
||||
|
||||
val crtFile = File.createTempFile("tmp.", ".file").apply { this.deleteOnExit() }
|
||||
crtFile.writeBytes(crt.data)
|
||||
|
||||
//openssl pkcs12 -export -out $(pfx_cert) -inkey $(rsa_key) -in $(crt_file) -password pass:$(thePassword) -name $(thePfxName)
|
||||
val cmd = "openssl pkcs12 -export " +
|
||||
" -inkey ${pk1File.path} " +
|
||||
" -in ${crtFile.path} " +
|
||||
" -password pass:${this.thePassword} -name ${this.name}"
|
||||
val ret = Helper.powerRun2(cmd, null)
|
||||
if (ret[0] as Boolean) {
|
||||
log.info("toPfx:error: ${String(ret[2] as ByteArray)}")
|
||||
log.info("toPfx:stdout: ${Hex.toHexString(ret[1] as ByteArray)}")
|
||||
this.data = ret[1] as ByteArray
|
||||
} else {
|
||||
log.error("stdout: " + String(ret[1] as ByteArray))
|
||||
log.error("stderr: " + String(ret[2] as ByteArray))
|
||||
throw RuntimeException()
|
||||
}
|
||||
}
|
||||
|
||||
//Zkeytool -importkeystore -deststorepass $(thePassword) -destkeystore $(jks_file) -srckeystore $(pfx_cert) -srcstoretype PKCS12 -srcstorepass $(thePassword)
|
||||
fun toJks(): Jks {
|
||||
val jksFile = File.createTempFile("tmp.", ".file").apply { this.delete() }
|
||||
val thisFile = File.createTempFile("tmp.", ".file").apply { this.deleteOnExit() }
|
||||
thisFile.writeBytes(this.data)
|
||||
val cmd = "keytool -importkeystore " +
|
||||
" -srcstorepass $thePassword -deststorepass $thePassword " +
|
||||
" -destkeystore ${jksFile.path} " +
|
||||
" -srckeystore $thisFile -srcstoretype PKCS12"
|
||||
val ret = Helper.powerRun2(cmd, null)
|
||||
if (ret[0] as Boolean) {
|
||||
log.info("toJks:error: " + String(ret[2] as ByteArray))
|
||||
log.info("toJks:stdout: " + String(ret[1] as ByteArray))
|
||||
this.data = ret[1] as ByteArray
|
||||
} else {
|
||||
log.error("stdout: " + String(ret[1] as ByteArray))
|
||||
log.error("stderr: " + String(ret[2] as ByteArray))
|
||||
throw RuntimeException()
|
||||
}
|
||||
val outDate = jksFile.readBytes()
|
||||
jksFile.delete()
|
||||
return Jks(this.name, outDate)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = LoggerFactory.getLogger(OpenSslHelper::class.java)
|
||||
fun decodePem(keyText: String): ByteArray {
|
||||
val publicKeyPEM = keyText
|
||||
.replace("-----BEGIN .*-----".toRegex(), "")
|
||||
.replace(System.lineSeparator().toRegex(), "")
|
||||
.replace("\n", "")
|
||||
.replace("\r", "")
|
||||
.replace("-----END .*-----".toRegex(), "")
|
||||
return Base64.getDecoder().decode(publicKeyPEM)
|
||||
}
|
||||
|
||||
fun toPfx(password: String = "somepassword", keyName: String = "androiddebugkey", pk1: PK1Key, crt: Crt) {
|
||||
val pk1File = File.createTempFile("tmp.", ".file").apply { this.deleteOnExit() }
|
||||
pk1File.writeBytes(pk1.data)
|
||||
|
||||
val crtFile = File.createTempFile("tmp.", ".file").apply { this.deleteOnExit() }
|
||||
crtFile.writeBytes(crt.data)
|
||||
|
||||
//openssl pkcs12 -export -out $(pfx_cert) -inkey $(rsa_key) -in $(crt_file) -password pass:$(thePassword) -name $(thePfxName)
|
||||
val cmd = "openssl pkcs12 -export -inkey ${pk1File.path} -in ${crtFile.path} -password pass:$password -name $keyName"
|
||||
val ret = Helper.powerRun2(cmd, null)
|
||||
if (ret[0] as Boolean) {
|
||||
log.info("toPfx:error: ${String(ret[2] as ByteArray)}")
|
||||
log.info("toPfx:stdout: ${Hex.toHexString(ret[1] as ByteArray)}")
|
||||
} else {
|
||||
log.error("stdout: " + String(ret[1] as ByteArray))
|
||||
log.error("stderr: " + String(ret[2] as ByteArray))
|
||||
throw RuntimeException()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +1 @@
|
||||
Subproject commit 23b636091aa768f141266dafa14f89fb4417eb5a
|
||||
Subproject commit d95de4b8d5d5fa7d36f3696e14be23d22fcdf7f5
|
Loading…
Reference in New Issue