lots of stuff
- extract helper for more projects - kotlin 1.4.31 - gradle 6.8.3 - vendor_boot flash/pull - fix comanion vbmeta update: boot.img, vendor_boot.img - refine libavbpull/53/head
parent
50273a9085
commit
6c662a54da
@ -1,47 +0,0 @@
|
||||
package cfig
|
||||
|
||||
import org.bouncycastle.asn1.pkcs.RSAPrivateKey
|
||||
import org.bouncycastle.util.io.pem.PemReader
|
||||
import java.io.InputStream
|
||||
import java.io.InputStreamReader
|
||||
import java.math.BigInteger
|
||||
import java.security.KeyFactory
|
||||
import java.security.PrivateKey
|
||||
import java.security.PublicKey
|
||||
import java.security.spec.PKCS8EncodedKeySpec
|
||||
import java.security.spec.RSAPrivateKeySpec
|
||||
import java.security.spec.RSAPublicKeySpec
|
||||
|
||||
class KeyUtil {
|
||||
companion object {
|
||||
@Throws(IllegalArgumentException::class)
|
||||
fun parsePemPrivateKey(inputStream: InputStream): RSAPrivateKey {
|
||||
val p = PemReader(InputStreamReader(inputStream)).readPemObject()
|
||||
if ("RSA PRIVATE KEY" != p.type) {
|
||||
throw IllegalArgumentException("input is not valid 'RSA PRIVATE KEY'")
|
||||
}
|
||||
return RSAPrivateKey.getInstance(p.content)
|
||||
}
|
||||
|
||||
fun parsePemPrivateKey2(inputStream: InputStream): PrivateKey {
|
||||
val rsa = parsePemPrivateKey(inputStream)
|
||||
return generateRsaPrivateKey(rsa.modulus, rsa.privateExponent)
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun parsePk8PrivateKey(inputData: ByteArray): PrivateKey {
|
||||
val spec = PKCS8EncodedKeySpec(inputData)
|
||||
return KeyFactory.getInstance("RSA").generatePrivate(spec)
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
private fun generateRsaPublicKey(modulus: BigInteger, publicExponent: BigInteger): PublicKey {
|
||||
return KeyFactory.getInstance("RSA").generatePublic(RSAPublicKeySpec(modulus, publicExponent))
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
private fun generateRsaPrivateKey(modulus: BigInteger, privateExponent: BigInteger): PrivateKey {
|
||||
return KeyFactory.getInstance("RSA").generatePrivate(RSAPrivateKeySpec(modulus, privateExponent))
|
||||
}
|
||||
}
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
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++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
import avb.alg.Algorithms
|
||||
import cfig.KeyUtil
|
||||
import cfig.helper.KeyHelper2
|
||||
import com.google.common.math.BigIntegerMath
|
||||
import org.apache.commons.codec.binary.Hex
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.math.BigInteger
|
||||
import java.math.RoundingMode
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.security.KeyFactory
|
||||
import java.security.KeyPairGenerator
|
||||
import java.security.Security
|
||||
import java.security.Signature
|
||||
import java.security.spec.PKCS8EncodedKeySpec
|
||||
import java.security.spec.X509EncodedKeySpec
|
||||
import javax.crypto.Cipher
|
||||
|
||||
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
class HelperTest {
|
||||
private val log = LoggerFactory.getLogger(HelperTest::class.java)
|
||||
|
||||
@Test
|
||||
fun rawSignTest() {
|
||||
val data = Hex.decodeHex("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d0609608648016503040201050004206317a4c8d86accc8258c1ac23ef0ebd18bc33010d7afb43b241802646360b4ab")
|
||||
val expectedSig = "28e17bc57406650ed78785fd558e7c1861cc4014c900d72b61c03cdbab1039e713b5bb19b556d04d276b46aae9b8a3999ccbac533a1cce00f83cfb83e2beb35ed7329f71ffec04fc2839a9b44e50abd66ea6c3d3bea6705e93e9139ecd0331170db18eba36a85a78bc49a5447260a30ed19d956cb2f8a71f6b19e57fdca43e052d1bb7840bf4c3efb47111f4d77764236d2e013fbf3b2577e4a3e01c9d166a5e890ef96210882e6e88ceca2fe3a2201f4961210d4ec6167f5dfd0e038e4a146f960caecab7d15ba65f6edcf5dbd25f5af543cfb8da4338bdbc872eec3f8e72aa8db679099e70952d3f7176c0b9111bf20ad1390eab1d09a859105816fdf92fbb"
|
||||
val privkFile = "../" + Algorithms.get("SHA256_RSA2048")!!.defaultKey.replace("pem", "pk8")
|
||||
val k = KeyHelper2.parseRsaPk8(Files.readAllBytes(Paths.get(privkFile)))
|
||||
val encData = KeyHelper2.rawSign(k, data)
|
||||
assertEquals(expectedSig, Hex.encodeHexString(encData))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun rawSignOpenSslTest() {
|
||||
val data = Hex.decodeHex("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d0609608648016503040201050004206317a4c8d86accc8258c1ac23ef0ebd18bc33010d7afb43b241802646360b4ab")
|
||||
val expectedSig = "28e17bc57406650ed78785fd558e7c1861cc4014c900d72b61c03cdbab1039e713b5bb19b556d04d276b46aae9b8a3999ccbac533a1cce00f83cfb83e2beb35ed7329f71ffec04fc2839a9b44e50abd66ea6c3d3bea6705e93e9139ecd0331170db18eba36a85a78bc49a5447260a30ed19d956cb2f8a71f6b19e57fdca43e052d1bb7840bf4c3efb47111f4d77764236d2e013fbf3b2577e4a3e01c9d166a5e890ef96210882e6e88ceca2fe3a2201f4961210d4ec6167f5dfd0e038e4a146f960caecab7d15ba65f6edcf5dbd25f5af543cfb8da4338bdbc872eec3f8e72aa8db679099e70952d3f7176c0b9111bf20ad1390eab1d09a859105816fdf92fbb"
|
||||
val sig = KeyHelper2.rawSignOpenSsl("../" + Algorithms.get("SHA256_RSA2048")!!.defaultKey, data)
|
||||
assertEquals(expectedSig, Hex.encodeHexString(sig))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test3() {
|
||||
val data = Hex.decodeHex("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d0609608648016503040201050004206317a4c8d86accc8258c1ac23ef0ebd18bc3301033")
|
||||
val signature = Signature.getInstance("NONEwithRSA")
|
||||
val keyFile = "../" + Algorithms.get("SHA256_RSA2048")!!.defaultKey.replace("pem", "pk8")
|
||||
val k = KeyUtil.parsePk8PrivateKey(Files.readAllBytes(Paths.get(keyFile)))
|
||||
signature.initSign(k)
|
||||
signature.update(data)
|
||||
println("data size " + data.size)
|
||||
println(signature.provider)
|
||||
val sig = signature.sign()
|
||||
println(sig)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCipher() {
|
||||
Security.addProvider(BouncyCastleProvider())
|
||||
for (p in Security.getProviders()) {
|
||||
println(p.toString())
|
||||
for (entry in p.entries) {
|
||||
println("\t" + entry.key.toString() + " -> " + entry.value)
|
||||
}
|
||||
println()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testKeys() {
|
||||
val kp = KeyPairGenerator.getInstance("rsa")
|
||||
.apply { this.initialize(2048) }
|
||||
.generateKeyPair()
|
||||
val pk8Spec = PKCS8EncodedKeySpec(kp.private.encoded) //kp.private.format == PKCS#8
|
||||
val x509Spec = X509EncodedKeySpec(kp.public.encoded) //kp.public.format == X.509
|
||||
|
||||
val kf = KeyFactory.getInstance("rsa")
|
||||
val privk = kf.generatePrivate(pk8Spec)
|
||||
val pubk = kf.generatePublic(x509Spec)
|
||||
println(pubk)
|
||||
|
||||
val cipher = Cipher.getInstance("RSA").apply {
|
||||
this.init(Cipher.ENCRYPT_MODE, privk)
|
||||
this.update("Good".toByteArray())
|
||||
}
|
||||
val encryptedText = Hex.encodeHexString(cipher.doFinal())
|
||||
println(encryptedText)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRSA() {
|
||||
// val r = BigIntegerMath.log2(BigInteger.valueOf(1024), RoundingMode.CEILING)
|
||||
// println(r)
|
||||
// println(BigInteger.valueOf(1024).mod(BigInteger.valueOf(2)))
|
||||
|
||||
val p = BigInteger.valueOf(3)
|
||||
val q = BigInteger.valueOf(7)
|
||||
val modulus = p.multiply(q)
|
||||
|
||||
val keyLength = BigIntegerMath.log2(modulus, RoundingMode.CEILING)
|
||||
println("keyLength = $keyLength")
|
||||
|
||||
//r = phi(n) = phi(p) * phi(q) = (p - 1)*(q - 1)
|
||||
val r = (p.subtract(BigInteger.ONE)).multiply(q - BigInteger.ONE)
|
||||
|
||||
//r ~ e
|
||||
//e is released as the public key exponent
|
||||
//most commonly e = 2^16 + 1 = 65,537
|
||||
val e = BigInteger.valueOf(5)
|
||||
|
||||
//(d * e).mod(r) == 1
|
||||
//d is kept as the private key exponent
|
||||
val d = e.modInverse(r)
|
||||
|
||||
println("p = $p, q = $q, modulus = $modulus , r = $r, e = $e, d = $d")
|
||||
assertEquals(1, d.multiply(e).mod(r).toInt())
|
||||
//private key: (modulus, d), d is calculated
|
||||
//pub key: (modulus, e) , e is chosen
|
||||
|
||||
val clearMsg = BigInteger.valueOf(10)
|
||||
val encMsg = clearMsg.pow(e.toInt()).mod(modulus)
|
||||
println("clear: $clearMsg, enc: $encMsg")
|
||||
}
|
||||
}
|
@ -1,22 +1,193 @@
|
||||
import avb.alg.Algorithms
|
||||
import cfig.KeyUtil
|
||||
import org.apache.commons.codec.binary.Hex
|
||||
import org.junit.Assert.*
|
||||
import cfig.helper.Helper
|
||||
import cfig.helper.KeyHelper
|
||||
import cfig.helper.KeyHelper2
|
||||
import com.google.common.math.BigIntegerMath
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import java.io.FileInputStream
|
||||
import java.io.File
|
||||
import java.math.BigInteger
|
||||
import java.math.RoundingMode
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.security.*
|
||||
import java.security.interfaces.RSAPrivateKey
|
||||
import java.security.spec.PKCS8EncodedKeySpec
|
||||
import java.security.spec.X509EncodedKeySpec
|
||||
import javax.crypto.Cipher
|
||||
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
class KeyUtilTest {
|
||||
@Test
|
||||
fun parseKeys() {
|
||||
val keyFile = "../" + Algorithms.get("SHA256_RSA2048")!!.defaultKey
|
||||
val k = KeyUtil.parsePk8PrivateKey(Files.readAllBytes(Paths.get(keyFile.replace("pem", "pk8"))))
|
||||
println("Key: $keyFile")
|
||||
val k = KeyHelper.parse(File(keyFile.replace("pem", "pk8")).readBytes()) as RSAPrivateKey
|
||||
println(k.privateExponent)
|
||||
println(k.modulus)
|
||||
val k2 = KeyHelper.parse(File(keyFile).readBytes()) as org.bouncycastle.asn1.pkcs.RSAPrivateKey
|
||||
println(k2.privateExponent)
|
||||
println(k2.modulus)
|
||||
//KeyHelper2.parseRsaPk8(FileInputStream(keyFile).readAllBytes())
|
||||
KeyHelper.parse(File(keyFile.replace("pem", "pk8")).readBytes())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun x1() {
|
||||
val p = BigInteger.valueOf(61L)
|
||||
val q = BigInteger.valueOf(53L)
|
||||
val modulus = p * q
|
||||
println(modulus)
|
||||
val exponent = 17
|
||||
val x = calcPrivateKey(p, q, exponent)
|
||||
println(x)
|
||||
//private key: modulus, x
|
||||
//public key: modulus, exponent
|
||||
|
||||
val data = 123L
|
||||
val encryptedData = enc(data, exponent, modulus)
|
||||
println("enc2 = " + encryptedData)
|
||||
val decryptedData = dec(encryptedData, x, modulus)
|
||||
println("dec2 data = " + decryptedData)
|
||||
}
|
||||
|
||||
fun calcPrivateKey(p: BigInteger, q: BigInteger, exponent: Int): Int {
|
||||
val modulus = p * q
|
||||
val phi = (p - BigInteger.ONE) * (q - BigInteger.ONE)
|
||||
return BigInteger.valueOf(exponent.toLong()).modInverse(phi).toInt()
|
||||
}
|
||||
|
||||
//data^{exp}
|
||||
fun enc(data: Long, exponent: Int, modulus: BigInteger): Long {
|
||||
return BigInteger.valueOf(data).pow(exponent).rem(modulus).toLong()
|
||||
}
|
||||
|
||||
val k2 = KeyUtil.parsePemPrivateKey2(FileInputStream(keyFile))
|
||||
println(Hex.encodeHexString(k.encoded))
|
||||
println(Hex.encodeHexString(k2.encoded))
|
||||
//data^{privateKey}
|
||||
fun dec(data: Long, privateKey: Int, modulus: BigInteger): Long {
|
||||
return BigInteger.valueOf(data).pow(privateKey).rem(modulus).toLong()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun rawSignTest() {
|
||||
val data =
|
||||
Helper.fromHexString("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d0609608648016503040201050004206317a4c8d86accc8258c1ac23ef0ebd18bc33010d7afb43b241802646360b4ab")
|
||||
val expectedSig =
|
||||
"28e17bc57406650ed78785fd558e7c1861cc4014c900d72b61c03cdbab1039e713b5bb19b556d04d276b46aae9b8a3999ccbac533a1cce00f83cfb83e2beb35ed7329f71ffec04fc2839a9b44e50abd66ea6c3d3bea6705e93e9139ecd0331170db18eba36a85a78bc49a5447260a30ed19d956cb2f8a71f6b19e57fdca43e052d1bb7840bf4c3efb47111f4d77764236d2e013fbf3b2577e4a3e01c9d166a5e890ef96210882e6e88ceca2fe3a2201f4961210d4ec6167f5dfd0e038e4a146f960caecab7d15ba65f6edcf5dbd25f5af543cfb8da4338bdbc872eec3f8e72aa8db679099e70952d3f7176c0b9111bf20ad1390eab1d09a859105816fdf92fbb"
|
||||
val privkFile = "../" + Algorithms.get("SHA256_RSA2048")!!.defaultKey.replace("pem", "pk8")
|
||||
val k = KeyHelper.parse(Files.readAllBytes(Paths.get(privkFile))) as PrivateKey
|
||||
val encData = KeyHelper2.rawSign(k, data)
|
||||
assertEquals(expectedSig, Helper.toHexString(encData))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun rawSignOpenSslTest() {
|
||||
val data =
|
||||
Helper.fromHexString("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d0609608648016503040201050004206317a4c8d86accc8258c1ac23ef0ebd18bc33010d7afb43b241802646360b4ab")
|
||||
val expectedSig =
|
||||
"28e17bc57406650ed78785fd558e7c1861cc4014c900d72b61c03cdbab1039e713b5bb19b556d04d276b46aae9b8a3999ccbac533a1cce00f83cfb83e2beb35ed7329f71ffec04fc2839a9b44e50abd66ea6c3d3bea6705e93e9139ecd0331170db18eba36a85a78bc49a5447260a30ed19d956cb2f8a71f6b19e57fdca43e052d1bb7840bf4c3efb47111f4d77764236d2e013fbf3b2577e4a3e01c9d166a5e890ef96210882e6e88ceca2fe3a2201f4961210d4ec6167f5dfd0e038e4a146f960caecab7d15ba65f6edcf5dbd25f5af543cfb8da4338bdbc872eec3f8e72aa8db679099e70952d3f7176c0b9111bf20ad1390eab1d09a859105816fdf92fbb"
|
||||
val sig = KeyHelper2.rawSignOpenSsl("../" + Algorithms.get("SHA256_RSA2048")!!.defaultKey, data)
|
||||
assertEquals(expectedSig, Helper.toHexString(sig))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test3() {
|
||||
val data =
|
||||
Helper.fromHexString("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d0609608648016503040201050004206317a4c8d86accc8258c1ac23ef0ebd18bc3301033")
|
||||
val signature = Signature.getInstance("NONEwithRSA")
|
||||
val keyFile = "../" + Algorithms.get("SHA256_RSA2048")!!.defaultKey.replace("pem", "pk8")
|
||||
val k = KeyHelper.parse(Files.readAllBytes(Paths.get(keyFile))) as PrivateKey
|
||||
signature.initSign(k)
|
||||
signature.update(data)
|
||||
println("data size " + data.size)
|
||||
println(signature.provider)
|
||||
val sig = signature.sign()
|
||||
println(sig)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCipher() {
|
||||
Security.addProvider(BouncyCastleProvider())
|
||||
for (p in Security.getProviders()) {
|
||||
println(p.toString())
|
||||
for (entry in p.entries) {
|
||||
println("\t" + entry.key.toString() + " -> " + entry.value)
|
||||
}
|
||||
println()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testKeys() {
|
||||
val kp = KeyPairGenerator.getInstance("rsa")
|
||||
.apply { this.initialize(2048) }
|
||||
.generateKeyPair()
|
||||
val pk8Spec = PKCS8EncodedKeySpec(kp.private.encoded) //kp.private.format == PKCS#8
|
||||
val x509Spec = X509EncodedKeySpec(kp.public.encoded) //kp.public.format == X.509
|
||||
|
||||
val kf = KeyFactory.getInstance("rsa")
|
||||
val privk = kf.generatePrivate(pk8Spec)
|
||||
val pubk = kf.generatePublic(x509Spec)
|
||||
println(pubk)
|
||||
|
||||
val cipher = Cipher.getInstance("RSA").apply {
|
||||
this.init(Cipher.ENCRYPT_MODE, privk)
|
||||
this.update("Good".toByteArray())
|
||||
}
|
||||
val encryptedText = Helper.toHexString(cipher.doFinal())
|
||||
println(encryptedText)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRSA() {
|
||||
// val r = BigIntegerMath.log2(BigInteger.valueOf(1024), RoundingMode.CEILING)
|
||||
// println(r)
|
||||
// println(BigInteger.valueOf(1024).mod(BigInteger.valueOf(2)))
|
||||
|
||||
val p = BigInteger.valueOf(3)
|
||||
val q = BigInteger.valueOf(7)
|
||||
val modulus = p.multiply(q)
|
||||
|
||||
val keyLength = BigIntegerMath.log2(modulus, RoundingMode.CEILING)
|
||||
println("keyLength = $keyLength")
|
||||
|
||||
//r = phi(n) = phi(p) * phi(q) = (p - 1)*(q - 1)
|
||||
val r = (p.subtract(BigInteger.ONE)).multiply(q - BigInteger.ONE)
|
||||
|
||||
//r ~ e
|
||||
//e is released as the public key exponent
|
||||
//most commonly e = 2^16 + 1 = 65,537
|
||||
val e = BigInteger.valueOf(5)
|
||||
|
||||
//(d * e).mod(r) == 1
|
||||
//d is kept as the private key exponent
|
||||
val d = e.modInverse(r)
|
||||
|
||||
println("p = $p, q = $q, modulus = $modulus , r = $r, e = $e, d = $d")
|
||||
assertEquals(1, d.multiply(e).mod(r).toInt())
|
||||
//private key: (modulus, d), d is calculated
|
||||
//pub key: (modulus, e) , e is chosen
|
||||
|
||||
val clearMsg = BigInteger.valueOf(10)
|
||||
val encMsg = clearMsg.pow(e.toInt()).mod(modulus)
|
||||
println("clear: $clearMsg, enc: $encMsg")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun listAll() {
|
||||
KeyHelper.listAll()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun signData() {
|
||||
val data = KeyUtilTest::class.java.classLoader.getResourceAsStream("data").readAllBytes()
|
||||
println(Helper.toHexString(data))
|
||||
val privKey = KeyHelper.parse(
|
||||
KeyUtilTest::class.java.classLoader.getResourceAsStream("testkey.pk8").readAllBytes()
|
||||
) as PrivateKey
|
||||
println("sha256=" + Helper.toHexString(KeyHelper2.sha256(data)))
|
||||
val signedHash = KeyHelper2.sha256rsa(data, privKey)
|
||||
println("Signed Hash: " + Helper.toHexString(signedHash))
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -0,0 +1,32 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
id("org.jetbrains.kotlin.jvm") version "1.4.31"
|
||||
`java-library`
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
||||
implementation("org.jetbrains.kotlin:kotlin-reflect")
|
||||
implementation("com.google.guava:guava:18.0")
|
||||
implementation("org.slf4j:slf4j-api:1.7.30")
|
||||
implementation("org.slf4j:slf4j-simple:1.7.30")
|
||||
implementation("org.apache.commons:commons-exec:1.3")
|
||||
implementation("org.bouncycastle:bcprov-jdk15on:1.57")
|
||||
implementation("org.apache.commons:commons-compress:1.20")
|
||||
|
||||
testImplementation("org.jetbrains.kotlin:kotlin-test")
|
||||
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
|
||||
testImplementation("com.fasterxml.jackson.core:jackson-annotations:2.12.1")
|
||||
testImplementation("com.fasterxml.jackson.core:jackson-databind:2.12.1")
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile>().all {
|
||||
kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
|
||||
kotlinOptions.jvmTarget = "1.8"
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package cfig.helper
|
||||
|
||||
import org.apache.commons.exec.CommandLine
|
||||
import org.apache.commons.exec.DefaultExecutor
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class AndroidHelper {
|
||||
companion object {
|
||||
private val log = LoggerFactory.getLogger(AndroidHelper::class.java)
|
||||
|
||||
fun signFile(signer: String,
|
||||
inFile: String,
|
||||
outFile: String,
|
||||
pemKey: String = "aosp/security/testkey.x509.pem",
|
||||
pk8Key: String = "aosp/security/testkey.pk8") {
|
||||
var cmd = "java -Xmx2048m -jar $signer "
|
||||
cmd += " -w "
|
||||
cmd += " $pemKey "
|
||||
cmd += " $pk8Key "
|
||||
cmd += " $inFile "
|
||||
cmd += " $outFile "
|
||||
log.info("signFile: $cmd")
|
||||
DefaultExecutor().execute(CommandLine.parse(cmd))
|
||||
}
|
||||
}
|
||||
}
|
@ -1,30 +1,17 @@
|
||||
package cfig.helper
|
||||
|
||||
import cfig.io.Struct3
|
||||
import com.google.common.math.BigIntegerMath
|
||||
import org.apache.commons.codec.binary.Hex
|
||||
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream
|
||||
import org.apache.commons.compress.compressors.gzip.GzipParameters
|
||||
import org.apache.commons.compress.compressors.xz.XZCompressorInputStream
|
||||
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.*
|
||||
import java.math.BigInteger
|
||||
import java.math.RoundingMode
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.nio.file.attribute.PosixFilePermission
|
||||
import java.security.MessageDigest
|
||||
import java.util.*
|
||||
import java.util.zip.GZIPInputStream
|
||||
import java.util.zip.GZIPOutputStream
|
||||
import java.util.zip.ZipException
|
||||
import javax.crypto.Cipher
|
||||
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
class Helper {
|
@ -0,0 +1,148 @@
|
||||
package cfig.helper
|
||||
|
||||
import cfig.io.Struct3
|
||||
import com.google.common.math.BigIntegerMath
|
||||
import org.bouncycastle.util.io.pem.PemReader
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.InputStreamReader
|
||||
import java.math.BigInteger
|
||||
import java.math.RoundingMode
|
||||
import java.security.KeyFactory
|
||||
import java.security.Security
|
||||
import java.security.cert.CertificateFactory
|
||||
import java.security.spec.PKCS8EncodedKeySpec
|
||||
import java.security.spec.RSAPrivateKeySpec
|
||||
import java.security.spec.RSAPublicKeySpec
|
||||
import java.security.spec.X509EncodedKeySpec
|
||||
import java.util.*
|
||||
|
||||
/*
|
||||
https://docs.oracle.com/javase/9/security/java-pki-programmers-guide.htm#JSSEC-GUID-650D0D53-B617-4055-AFD3-AF5C2629CBBF
|
||||
https://www.baeldung.com/java-read-pem-file-keys
|
||||
*/
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
class KeyHelper {
|
||||
companion object {
|
||||
private val log = LoggerFactory.getLogger(KeyHelper::class.java)
|
||||
|
||||
fun getPemContent(keyText: String): ByteArray {
|
||||
val publicKeyPEM = keyText
|
||||
.replace("-----BEGIN PUBLIC KEY-----", "")
|
||||
.replace("-----END PUBLIC KEY-----", "")
|
||||
.replace("-----BEGIN RSA PRIVATE KEY-----", "")
|
||||
.replace("-----END RSA PRIVATE KEY-----", "")
|
||||
.replace(System.lineSeparator().toRegex(), "")
|
||||
.replace("\n", "")
|
||||
.replace("\r", "")
|
||||
return Base64.getDecoder().decode(publicKeyPEM)
|
||||
}
|
||||
|
||||
/*
|
||||
in: modulus, public expo
|
||||
out: PublicKey
|
||||
|
||||
in: modulus, private expo
|
||||
out: PrivateKey
|
||||
*/
|
||||
fun makeKey(modulus: BigInteger, exponent: BigInteger, isPublicExpo: Boolean): Any {
|
||||
return if (isPublicExpo) {
|
||||
KeyFactory.getInstance("RSA").generatePublic(RSAPublicKeySpec(modulus, exponent))
|
||||
} else {
|
||||
KeyFactory.getInstance("RSA").generatePrivate(RSAPrivateKeySpec(modulus, exponent))
|
||||
}
|
||||
}
|
||||
|
||||
fun parse(data: ByteArray): Any {
|
||||
val p = PemReader(InputStreamReader(ByteArrayInputStream(data))).readPemObject()
|
||||
return if (p != null) {
|
||||
log.debug("parse PEM: " + p.type)
|
||||
when (p.type) {
|
||||
"RSA PUBLIC KEY" -> {
|
||||
org.bouncycastle.asn1.pkcs.RSAPublicKey.getInstance(p.content) as org.bouncycastle.asn1.pkcs.RSAPublicKey
|
||||
}
|
||||
"RSA PRIVATE KEY" -> {
|
||||
org.bouncycastle.asn1.pkcs.RSAPrivateKey.getInstance(p.content) as org.bouncycastle.asn1.pkcs.RSAPrivateKey
|
||||
}
|
||||
"PUBLIC KEY" -> {
|
||||
val keySpec = X509EncodedKeySpec(p.content)
|
||||
KeyFactory.getInstance("RSA").generatePublic(keySpec) as java.security.interfaces.RSAPublicKey
|
||||
}
|
||||
"PRIVATE KEY" -> {
|
||||
val keySpec = PKCS8EncodedKeySpec(p.content)
|
||||
KeyFactory.getInstance("RSA").generatePrivate(keySpec) as java.security.interfaces.RSAPrivateKey
|
||||
}
|
||||
"CERTIFICATE" -> {
|
||||
CertificateFactory.getInstance("X.509").generateCertificate(ByteArrayInputStream(p.content))
|
||||
}
|
||||
else -> throw IllegalArgumentException("unsupported type: ${p.type}")
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
val spec = PKCS8EncodedKeySpec(data)
|
||||
val privateKey = KeyFactory.getInstance("RSA").generatePrivate(spec)
|
||||
log.debug("Parse PKCS8: Private")
|
||||
privateKey
|
||||
} catch (e: java.security.spec.InvalidKeySpecException) {
|
||||
log.debug("Parse X509: Public")
|
||||
val spec = X509EncodedKeySpec(data)
|
||||
KeyFactory.getInstance("RSA").generatePublic(spec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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(rsa: org.bouncycastle.asn1.pkcs.RSAPrivateKey): ByteArray {
|
||||
assert(65537.toBigInteger() == rsa.publicExponent)
|
||||
val numBits: Int = BigIntegerMath.log2(rsa.modulus, RoundingMode.CEILING)
|
||||
assert(rsa.modulus.bitLength() == numBits)
|
||||
val b = BigInteger.valueOf(2).pow(32)
|
||||
val n0inv = b.minus(rsa.modulus.modInverse(b)).toLong()
|
||||
val rrModn = BigInteger.valueOf(4).pow(numBits).rem(rsa.modulus)
|
||||
val unsignedModulo = rsa.modulus.toByteArray().sliceArray(1..numBits / 8) //remove sign byte
|
||||
return Struct3("!II${numBits / 8}b${numBits / 8}b").pack(
|
||||
numBits,
|
||||
n0inv,
|
||||
unsignedModulo,
|
||||
rrModn.toByteArray()
|
||||
)
|
||||
}
|
||||
|
||||
fun decodeRSAkey(key: ByteArray): java.security.interfaces.RSAPublicKey {
|
||||
val ret = Struct3("!II").unpack(ByteArrayInputStream(key))
|
||||
val numBits = (ret[0] as UInt).toInt()
|
||||
val n0inv = (ret[1] as UInt).toLong()
|
||||
val ret2 = Struct3("!II${numBits / 8}b${numBits / 8}b").unpack(ByteArrayInputStream(key))
|
||||
val unsignedModulo = ret2[2] as ByteArray
|
||||
val rrModn = BigInteger(ret2[3] as ByteArray)
|
||||
log.debug("n0inv=$n0inv, unsignedModulo=${Helper.toHexString(unsignedModulo)}, rrModn=$rrModn")
|
||||
val exponent = 65537L
|
||||
val modulus = BigInteger(Helper.join(Struct3("x").pack(0), unsignedModulo))
|
||||
val keySpec = RSAPublicKeySpec(modulus, BigInteger.valueOf(exponent))
|
||||
return KeyFactory.getInstance("RSA").generatePublic(keySpec) as java.security.interfaces.RSAPublicKey
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
|
||||
for ((i, item) in Security.getAlgorithms("Cipher").withIndex()) {
|
||||
log.info("Cipher: $i -> $item")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
package cfig.helper
|
||||
|
||||
import cfig.helper.OpenSslHelper.Companion.decodePem
|
||||
import org.junit.Test
|
||||
import org.slf4j.LoggerFactory
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class OpenSslHelperTest {
|
||||
private val log = LoggerFactory.getLogger(OpenSslHelperTest::class.java)
|
||||
|
||||
@Test
|
||||
fun PKCS1test() {
|
||||
//private RSA key
|
||||
val rsa = OpenSslHelper.PK1Key.generate(4096).apply {
|
||||
val fileName = "1_rsa.key"
|
||||
writeTo(fileName)
|
||||
}
|
||||
|
||||
//Action-1: private RSA key -> RSA public key(PEM)
|
||||
val rsaPubPEM = rsa.getPublicKey(OpenSslHelper.KeyFormat.PEM).apply {
|
||||
writeTo("2_rsa_pub.pem.key")
|
||||
}
|
||||
//Action-3: RSA public key(PEM) --> RSA public key(DER)
|
||||
val decodeFromPem = decodePem(String(rsaPubPEM.data))
|
||||
|
||||
//Action-2: private RSA key -> RSA public key(DER)
|
||||
val rsaPubDer = rsa.getPublicKey(OpenSslHelper.KeyFormat.DER).apply {
|
||||
writeTo("3_rsa_pub.der.key")
|
||||
}
|
||||
|
||||
//check equality: 1,3 == 2
|
||||
assertTrue(decodeFromPem.contentEquals(rsaPubDer.data))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun PKCS8Test() {
|
||||
//private RSA key
|
||||
val rsa = OpenSslHelper.PK1Key.generate(4096)
|
||||
|
||||
run { //check equality: 8 == 4,5
|
||||
val pk8Pub = rsa.getPk8PublicKey()
|
||||
val pk8Pub2 = rsa.toPk8(OpenSslHelper.KeyFormat.PEM).getPublicKey()
|
||||
assert(pk8Pub.data.contentEquals(pk8Pub2.data))
|
||||
}
|
||||
|
||||
run { //check equality: 8 == 4,5
|
||||
val pk8Pub = rsa.getPk8PublicKey()
|
||||
val action8_11 = decodePem(String(pk8Pub.data))
|
||||
// val pk8Pub2 = rsa.toPk8(OpenSslHelper.KeyFormat.PEM).getPublicKey()
|
||||
// assert(pk8Pub.data.contentEquals(pk8Pub2.data))
|
||||
}
|
||||
|
||||
//check equality: 4,9 == original RSA
|
||||
rsa.toPk8(OpenSslHelper.KeyFormat.PEM).let { pk8Pem ->
|
||||
val shortConversion = pk8Pem.toPk1()
|
||||
assert(shortConversion.data.contentEquals(rsa.data))
|
||||
}
|
||||
|
||||
//check equality: 7,10,9 == original RSA
|
||||
rsa.toPk8(OpenSslHelper.KeyFormat.DER).let { pk8der ->
|
||||
val longConversion = pk8der
|
||||
.transform(OpenSslHelper.KeyFormat.DER, OpenSslHelper.KeyFormat.PEM) //pk8 PEM
|
||||
.toPk1() //pk1 PEM
|
||||
assert(longConversion.data.contentEquals(rsa.data))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun CertTest() {
|
||||
//private RSA key
|
||||
val rsa = OpenSslHelper.PK1Key.generate(4096)
|
||||
val crt = rsa.toV1Cert()
|
||||
val jks = crt.toJks()
|
||||
//jks.writeTo("good.jks")
|
||||
val pfx = OpenSslHelper.Pfx(name = "androiddebugkey", thePassword = "somepassword")
|
||||
pfx.generate(rsa, crt)
|
||||
val jks2 = pfx.toJks()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun androidCertTest() {
|
||||
//platform.x509.pem: Certificate, PEM
|
||||
val crt = OpenSslHelper.Crt(data = this.javaClass.classLoader.getResourceAsStream("platform.x509.pem").readBytes())
|
||||
val jks = crt.toJks()
|
||||
//jks.writeTo("platform.jks")
|
||||
jks.check()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun androidPk8Test() {
|
||||
//platform.pk8: Private Key, PKCS#8, DER encoding
|
||||
val pk8rsa = OpenSslHelper.PK8RsaKey(OpenSslHelper.KeyFormat.DER,
|
||||
this.javaClass.classLoader.getResourceAsStream("platform.pk8").readBytes())
|
||||
val pk1 = pk8rsa
|
||||
.transform(OpenSslHelper.KeyFormat.DER, OpenSslHelper.KeyFormat.PEM)
|
||||
.toPk1()
|
||||
val crt = OpenSslHelper.Crt(data = this.javaClass.classLoader.getResourceAsStream("platform.x509.pem").readBytes())
|
||||
val pfx = OpenSslHelper.Pfx(name = "androiddebugkey", thePassword = "somepassword").apply {
|
||||
this.generate(pk1, crt)
|
||||
}
|
||||
pfx.toJks().writeTo("platform.jks")
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package cfig.helper
|
||||
|
||||
import cfig.helper.ZipHelper.Companion.dumpEntry
|
||||
import org.apache.commons.compress.archivers.zip.ZipFile
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
|
||||
class ZipHelperTest {
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
File("out").let {
|
||||
if (!it.exists()) it.mkdir()
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
File("out").deleteRecursively()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun unzip() {
|
||||
val zf = ZipHelperTest::class.java.classLoader.getResource("appcompat.zip").file
|
||||
ZipHelper.unzip(File(zf).path, "out")
|
||||
File("out").deleteRecursively()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun dumpEntry() {
|
||||
val zf = ZipHelperTest::class.java.classLoader.getResource("appcompat.zip").file
|
||||
ZipFile(zf).use {
|
||||
it.dumpEntry("webview.log", File("out/webview.log"))
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,27 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEqDCCA5CgAwIBAgIJALOZgIbQVs/6MA0GCSqGSIb3DQEBBAUAMIGUMQswCQYD
|
||||
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4g
|
||||
VmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UE
|
||||
AxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
|
||||
Fw0wODA0MTUyMjQwNTBaFw0zNTA5MDEyMjQwNTBaMIGUMQswCQYDVQQGEwJVUzET
|
||||
MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4G
|
||||
A1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9p
|
||||
ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZI
|
||||
hvcNAQEBBQADggENADCCAQgCggEBAJx4BZKsDV04HN6qZezIpgBuNkgMbXIHsSAR
|
||||
vlCGOqvitV0Amt9xRtbyICKAx81Ne9smJDuKgGwms0sTdSOkkmgiSQTcAUk+fArP
|
||||
GgXIdPabA3tgMJ2QdNJCgOFrrSqHNDYZUer3KkgtCbIEsYdeEqyYwap3PWgAuer9
|
||||
5W1Yvtjo2hb5o2AJnDeoNKbf7be2tEoEngeiafzPLFSW8s821k35CjuNjzSjuqtM
|
||||
9TNxqydxmzulh1StDFP8FOHbRdUeI0+76TybpO35zlQmE1DsU1YHv2mi/0qgfbX3
|
||||
6iANCabBtJ4hQC+J7RGQiTqrWpGA8VLoL4WkV1PPX8GQccXuyCcCAQOjgfwwgfkw
|
||||
HQYDVR0OBBYEFE/koLPdnLop9x1yh8Tnw48ghsKZMIHJBgNVHSMEgcEwgb6AFE/k
|
||||
oLPdnLop9x1yh8Tnw48ghsKZoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UE
|
||||
CBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMH
|
||||
QW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAG
|
||||
CSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJALOZgIbQVs/6MAwGA1Ud
|
||||
EwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADggEBAFclUbjZOh9z3g9tRp+G2tZwFAAp
|
||||
PIigzXzXeLc9r8wZf6t25iEuVsHHYc/EL9cz3lLFCuCIFM78CjtaGkNGBU2Cnx2C
|
||||
tCsgSL+ItdFJKe+F9g7dEtctVWV+IuPoXQTIMdYT0Zk4u4mCJH+jISVroS0dao+S
|
||||
6h2xw3Mxe6DAN/DRr/ZFrvIkl5+6bnoUvAJccbmBOM7z3fwFlhfPJIRc97QNY4L3
|
||||
J17XOElatuWTG5QhdlxJG3L7aOCA29tYwgKdNHyLMozkPvaosVUz7fvpib1qSN1L
|
||||
IC7alMarjdW4OZID2q4u1EYjLk/pvZYTlMYwDlE448/Shebk5INTjLixs1c=
|
||||
-----END CERTIFICATE-----
|
Binary file not shown.
@ -0,0 +1,9 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEA1pMZBN7GCySx7cdi4NnY
|
||||
JT4+zWzrHeL/Boyo6LyozWvTeG6nCqds5g67D5k1Wf/ZPnepQ+foPUtkuOT+otPm
|
||||
VvHiZ6gbv7IwtXjCBEO+THIYuEb1IRWG8DihTonCvjh/jr7Pj8rD2h7jMMnqk9Cn
|
||||
w9xK81AiDVAIBzLggJcX7moFM1nmppTsLLPyhKCkZsh6lNg7MQk6ZzcuL2QSwG5t
|
||||
QvFYGN/+A4HMDNRE2mzdw7gkWBlIAbMlZBNPv96YySh3SNv1Z2pUDYFUyLvKB7ni
|
||||
R1UzEcRrmvdv3uzMjmnnyKLQjngmIJQ/mXJ9PAT+cpkdmd+brjigshd/ox1bav7p
|
||||
HwIBAw==
|
||||
-----END PUBLIC KEY-----
|
@ -0,0 +1,27 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEqDCCA5CgAwIBAgIJAJNurL4H8gHfMA0GCSqGSIb3DQEBBQUAMIGUMQswCQYD
|
||||
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4g
|
||||
VmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UE
|
||||
AxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
|
||||
Fw0wODAyMjkwMTMzNDZaFw0zNTA3MTcwMTMzNDZaMIGUMQswCQYDVQQGEwJVUzET
|
||||
MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4G
|
||||
A1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9p
|
||||
ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZI
|
||||
hvcNAQEBBQADggENADCCAQgCggEBANaTGQTexgskse3HYuDZ2CU+Ps1s6x3i/waM
|
||||
qOi8qM1r03hupwqnbOYOuw+ZNVn/2T53qUPn6D1LZLjk/qLT5lbx4meoG7+yMLV4
|
||||
wgRDvkxyGLhG9SEVhvA4oU6Jwr44f46+z4/Kw9oe4zDJ6pPQp8PcSvNQIg1QCAcy
|
||||
4ICXF+5qBTNZ5qaU7Cyz8oSgpGbIepTYOzEJOmc3Li9kEsBubULxWBjf/gOBzAzU
|
||||
RNps3cO4JFgZSAGzJWQTT7/emMkod0jb9WdqVA2BVMi7yge54kdVMxHEa5r3b97s
|
||||
zI5p58ii0I54JiCUP5lyfTwE/nKZHZnfm644oLIXf6MdW2r+6R8CAQOjgfwwgfkw
|
||||
HQYDVR0OBBYEFEhZAFY9JyxGrhGGBaR0GawJyowRMIHJBgNVHSMEgcEwgb6AFEhZ
|
||||
AFY9JyxGrhGGBaR0GawJyowRoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UE
|
||||
CBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMH
|
||||
QW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAG
|
||||
CSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJAJNurL4H8gHfMAwGA1Ud
|
||||
EwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHqvlozrUMRBBVEY0NqrrwFbinZa
|
||||
J6cVosK0TyIUFf/azgMJWr+kLfcHCHJsIGnlw27drgQAvilFLAhLwn62oX6snb4Y
|
||||
LCBOsVMR9FXYJLZW2+TcIkCRLXWG/oiVHQGo/rWuWkJgU134NDEFJCJGjDbiLCpe
|
||||
+ZTWHdcwauTJ9pUbo8EvHRkU3cYfGmLaLfgn9gP+pWA7LFQNvXwBnDa6sppCccEX
|
||||
31I828XzgXpJ4O+mDL1/dBd+ek8ZPUP0IgdyZm5MTYPhvVqGCHzzTy3sIeJFymwr
|
||||
sBbmg2OAUNLEMO6nwmocSdN2ClirfxqCzJOLSDE4QyS9BAH6EhY6UFcOaE0=
|
||||
-----END CERTIFICATE-----
|
Loading…
Reference in New Issue