java 动态生成证书_android平台使用java动态生成公私钥,并导出证书文件

不依赖keytool工具,指令生成证书库,而是java代码生成,且导出到证书文件中。直接上代码:

证书工具类:

package com.daobo.security.utils

import com.daobo.security.bean.Certification

import org.bouncycastle.jce.provider.BouncyCastleProvider

import org.bouncycastle.x509.X509V1CertificateGenerator

import sun.misc.BASE64Decoder

import sun.misc.BASE64Encoder

import java.io.BufferedInputStream

import java.io.FileInputStream

import java.math.BigInteger

import java.security.*

import java.security.Security.addProvider

import java.security.cert.CertificateFactory

import java.security.cert.X509Certificate

import java.security.spec.PKCS8EncodedKeySpec

import java.security.spec.RSAKeyGenParameterSpec

import java.util.*

import javax.security.auth.x500.X500Principal

object CertificationUtil {

const val strDnInfo : String = "CN=Test Certificate"

/**

* @param pair 密钥对

* @param startDate 有效期

* @param endDate 有效期

* @param info 证书信息

* @return

* @throws InvalidKeyException

* @throws NoSuchProviderException

* @throws SignatureException

*/

@Throws(InvalidKeyException::class, NoSuchProviderException::class, SignatureException::class)

@SuppressWarnings("deprecation")

fun generateV1Certificate(pair: KeyPair, startDate: Date, endDate: Date, info: X500Principal): X509Certificate {

// generate the certificate

addProvider(BouncyCastleProvider())

val certGen = X509V1CertificateGenerator()

certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()))

certGen.setIssuerDN(info)

certGen.setNotBefore(startDate)

certGen.setNotAfter(endDate)

certGen.setSubjectDN(X500Principal(strDnInfo))

certGen.setPublicKey(pair.public)

// i get error here

certGen.setSignatureAlgorithm("SHA256WithRSAEncryption")

return certGen.generateX509Certificate(pair.private, "BC")

}

/**

* * 生成证书文件

* @param address 文件保存的路径

* @param startDate 有效期

* @param endDate 有效期

* @param info 证书信息

* @param algorithm 算法名称

* @param keySize 密钥长度

* @param random 随机源

* @throws Exception

*/

@Throws(Exception::class)

fun writeFilePkCert(fileName: String, startDate: Date, endDate: Date, info: X500Principal,

algorithm: String, keySize: Int, random: SecureRandom, kpGen : Certification) {

// create the keys

val kp = kpGen.getKeyPair(algorithm, keySize, random)

// generate the certificate

val cert = generateV1Certificate(kp, startDate, endDate, info)

// show some basic validation

cert.checkValidity(Date())

cert.verify(cert.publicKey)

CertFileUtil.getInstance(null).writeToFile(fileName,

BASE64Encoder().encode(cert.encoded))

//System.out.println("valid certificate generated:"+cert.getPublicKey());

}

@Throws(Exception::class)

fun writeFileSkCert(fileName: String, kpGen : Certification) {

//直接将私钥 string 写进到文件

CertFileUtil.getInstance(null).writeToFile(fileName,

getKeyAsString(kpGen.privateKey!!))

//System.out.println("valid certificate generated:"+cert.getPublicKey());

}

fun getKeyAsString(key: Key): String {

val keyBytes = key.encoded

val b64 = BASE64Encoder()

return b64.encode(keyBytes)

}

//将String类型转换为PrivateKey类型

@Throws(Exception::class)

fun getPrivateKeyFromString(key: String, algorithm: String): PrivateKey {

val keyFactory = KeyFactory.getInstance(algorithm)

val b64 = BASE64Decoder()

val privateKeySpec = PKCS8EncodedKeySpec(b64.decodeBuffer(key))

return keyFactory.generatePrivate(privateKeySpec)

}

/**

* 获取证书对象

* @param address 证书文件路径

* @return

* @throws Exception

*/

@Throws(Exception::class)

fun getCert(address: String): X509Certificate? {

var cert: X509Certificate? = null

val fis = FileInputStream(address)

val bis = BufferedInputStream(fis)

val cf = CertificateFactory.getInstance("X.509")

while (bis.available() > 0) {

cert = cf.generateCertificate(fis) as X509Certificate?

}

return cert

}

}

certification Bean:

package com.daobo.security.bean

import java.math.BigInteger

import java.security.*

import java.text.SimpleDateFormat

import java.util.*

import javax.crypto.Cipher

class Certification {

var strName : String = ""

var strCreateTime : String = ""

var strEffectiveTime : String = ""

// 私钥:

var privateKey: PrivateKey? = null

// 公钥:

var publicKey: PublicKey? = null

constructor(name : String, createTime : String, effectiveTime: String){

strName = name

strCreateTime = createTime

strEffectiveTime = effectiveTime

}

constructor(name : String, effectiveTime : String) {

this.strName = name

this.strEffectiveTime = effectiveTime

val format = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")

strCreateTime = format.format(Date())

}

@Throws(GeneralSecurityException::class, NoSuchAlgorithmException::class)

fun getKeyPair(algorithm : String, keySize : Int, random : SecureRandom) : KeyPair {

val kpGen = KeyPairGenerator.getInstance(algorithm)

kpGen.initialize(keySize, random)

val keyPair = kpGen.generateKeyPair()

this.privateKey = keyPair!!.private

this.publicKey = keyPair!!.public

return keyPair

}

fun isExpired () : Boolean {

var date = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(strEffectiveTime)

if(date.before(Date())){

return true

}

return false

}

// 把私钥导出为字节

fun getPrivateKey(): ByteArray {

return this.privateKey!!.encoded

}

// 把公钥导出为字节

fun getPublicKey(): ByteArray {

return this.publicKey!!.encoded

}

// 用公钥加密:

@Throws(GeneralSecurityException::class)

fun encrypt(message: ByteArray): ByteArray {

val cipher = Cipher.getInstance("RSA")

cipher.init(Cipher.ENCRYPT_MODE, this.publicKey)

return cipher.doFinal(message)

}

// 用私钥解密:

@Throws(GeneralSecurityException::class)

fun decrypt(input: ByteArray): ByteArray {

val cipher = Cipher.getInstance("RSA")

cipher.init(Cipher.DECRYPT_MODE, this.privateKey)

return cipher.doFinal(input)

}

}

写文件的工具类:

package com.daobo.security.utils

import android.content.Context

import android.os.Environment

import java.io.File

import java.io.FileInputStream

import java.io.FileOutputStream

import java.io.OutputStreamWriter

import java.nio.charset.Charset

class CertFileUtil {

private var applicationContext : Context? = null

var certRootPath : String = ""

companion object {

private var instance: CertFileUtil? = null

fun getInstance(context: Context?): CertFileUtil {

if (instance == null)

instance = CertFileUtil(context)

return instance!!

}

}

private constructor (context: Context?) {

this.applicationContext = context

LogUtil.init(LogUtil.INFO_LEVEL, "$certRootPath/daobo/log/")

val state = Environment.getExternalStorageState()

if (Environment.MEDIA_MOUNTED == state) {

// 已经挂载了sd卡

certRootPath = Environment.getExternalStoragePublicDirectory(

Environment.DIRECTORY_DOWNLOADS).absolutePath

certRootPath += "/daobo/cert/"

} else {

LogUtil.info( "=== 读取 sd 状态不可用!===")

}

}

fun certPKFileName (certName : String) : String {

return certName + "_pk.cer"

}

fun certSKFileName (certName : String) : String {

return certName + "_sk.cer"

}

fun writeToFile(fileName : String, fileData : String) {

try {

val filePath = File(certRootPath)

if (!filePath.exists()) {

filePath.mkdirs()

}

val file = File(filePath, fileName)

val fos = FileOutputStream(file)

val wr = OutputStreamWriter(fos, Charset.forName("UTF-8"))

//wr.write("-----BEGIN CERTIFICATE-----\n")

wr.write(fileData)

//wr.write("\n-----END CERTIFICATE-----\n")

wr.flush()

wr.close()

//val fos = FileOutputStream(file)

//fos.write(fileData)

//fos.flush()

fos.close()

}catch (e:Exception) {

e.printStackTrace()

}

}

fun readCertFile(fileName : String) : ByteArray {

var filePath = File(certRootPath)

var files = filePath.listFiles()

if(files == null || files.isEmpty()){

//Toast.makeText(context, "文件为空!", Toast.LENGTH_SHORT).show()

LogUtil.info("directory=daoboCert=== 文件为空!===")

return ByteArray(0)

}

// 拿到输入流

for(f in files){

if(fileName == f.name){

val input = FileInputStream(files[0])

try {

// 建立存储器

var buf = ByteArray(input.available())

// 读取到存储器

input.read(buf)

return buf

} catch (e: Exception) {

e.printStackTrace()

}finally {

// 关闭输入流

input.close()

}

}

}

return ByteArray(0)

}

}

说明下,需要依赖一个证书的库:bcprov-jdk15to18-165.jar (bouncycastle)链接,还需要单独去下载一个Android使用的base64编码的工具jar

公钥是有对应的生成cer证书的操作,但是私钥没有,一半经过base64直接写到文件中。公钥证书有几个关键的证书参数:

//获取发布者标识

Principal principalIssuer = x509Certificate.getIssuerDN();

//获取证书的主体标识

Principal principalSubject = x509Certificate.getSubjectDN();

//保存证书的序列号

list.add(x509Certificate.getSerialNumber())

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值