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())

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438604.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第八节:Task的各类TaskTResult返回值以及通用线程的异常处理方案

一. Task的各种返回值-Task<TResult> PS&#xff1a; 在前面章节&#xff0c;我们介绍了Task类开启线程、线程等待、线程延续的方式&#xff0c;但我们并没有关注这些方式的返回值&#xff0c;其实他们都是有返回值的Task<TResult>&#xff0c;然后可以通过Task的…

mysql profile 导出_MySQL数据的导出和导入工具:mysqldump_MySQL

mysqldump导出要用到MySQL的mysqldump工具&#xff0c;基本用法是&#xff1a;shell> mysqldump [OPTIONS] database [tables]如果你不给定任何表&#xff0c;整个数据库将被导出。通过执行mysqldump --help&#xff0c;你能得到你mysqldump的版本支持的选项表。注意&#x…

mysql2005触发器修改成绩_创建、更改和删除触发器

创建、更改和删除触发器Creating, Altering, and Removing Triggers08/06/2017本文内容适用于&#xff1a;Applies to: SQL ServerSQL Server(所有支持的版本)SQL ServerSQL Server (all supported versions) Azure SQL 数据库Azure SQL DatabaseAzure SQL 数据库Azure SQL Dat…

第一节:从面向对象思想(oo)开发、接口、抽象类以及二者比较

一. 面向对象思想 1. 面向过程&#xff08;OP&#xff09;和面向对象&#xff08;OO&#xff09;的区别&#xff1a; (1)&#xff1a;面向过程就是排着用最简单的代码一步一步写下去&#xff0c;没有封装&#xff0c;当业务复杂的时候&#xff0c;改动就很麻烦了 (2)&#xff…

业务异常 java_谈谈RxJava处理业务异常的几种方式

此文介绍了RxJava处理业务异常的几种方式&#xff0c;分享给大伙。具体如下&#xff1a;关于异常Java的异常可以分为两种&#xff1a;运行时异常和检查性异常。运行时异常&#xff1a;RuntimeException类及其子类都被称为运行时异常&#xff0c;这种异常的特点是Java编译器不去…

第二节:重写(new)、覆写(overwrite)、和重载(overload)

一. 重写 1. 关键字&#xff1a;new 2. 含义&#xff1a;子类继承父类中的普通方法&#xff0c;如果在子类中重写了一个和父类中完全相同的方法&#xff0c;子类中会报警告(问是否显式的隐藏父类的中的方法)&#xff0c;如果在子类中的方法前加上new关键字&#xff0c;则警告…

java 分页查询_JavaWeb之分页查询

时间&#xff1a;2016-12-11 01:411、分页的优点&#xff1a;只查询一页&#xff0c;不需要查询所有数据&#xff0c;能够提高效率。2、分页数据页面的数据都是由Servlet传递的* 当前页&#xff1a;pageCode> 如果页面没有向Servlet传递页码&#xff0c;那么Servlet默认…

第三节:深度剖析各类数据结构(Array、List、Queue、Stack)及线程安全问题和yeild关键字

一. 各类数据结构比较及其线程安全问题 1. Array(数组)&#xff1a; 分配在连续内存中,不能随意扩展&#xff0c;数组中数值类型必须是一致的。数组的声明有两种形式&#xff1a;直接定义长度&#xff0c;然后赋值&#xff1b;直接赋值。 缺点&#xff1a;插入数据慢。 优点&a…

java万法_Java I/O库的设计分析

Java采用了流的机制来实现输入&#xff0f;输出。所谓流&#xff0c;就是数据的有序排列。而流可以是从某个源(称为流源或Source of Stream)出来&#xff0c;到某个目的地(称为流汇或Sink of Stream)去的。由流的方向&#xff0c;可以分成输入流和输出流。一个程序从输入流读取…

第四节:IO、序列化和反序列化、加密解密技术

一. IO读写   这里主要包括文件的读、写、移动、复制、删除、文件夹的创建、文件夹的删除等常规操作。 注意&#xff1a;这里需要特别注意&#xff0c;对于普通的控制台程序和Web程序&#xff0c;将"相对路径"转换成"绝对路径"的方法不一致。 (1). 在w…

java mediator_java—mediator中介模式

中介者模式是由GoF提出的23种软件设计模式的一种。Mediator模式是行为模式之一&#xff0c;Mediator模式定义:用一个中介者对象来封装一系列的对象交互。中介者使各对象不需要显式的相互引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立的改变他们之间的交互。适用性…

第五节:泛型(泛型类、接口、方法、委托、泛型约束、泛型缓存、逆变和协变)

一. 泛型诞生的背景 在介绍背景之前&#xff0c;先来看一个案例&#xff0c;要求&#xff1a;分别输出实体model1、model2、model3的id和name值,这三个实体有相同的属性名字id和name。 1 public class myUtils2 {3 //要求&#xff1a;分别输出实体model1、model2、…

第六节:反射(几种写法、好处和弊端、利用反射实现IOC)

一. 加载dll,读取相关信息 1. 加载程序集的三种方式 调用Assembly类下的三个方法&#xff1a;Load、LoadFile、LoadFrom。 1       //1.1 Load方法&#xff1a;动态默认加载当前路径下的(bin)下的dll文件,不需要后缀 2 Assembly assembly Assembly.Load(&…

第七节:语法总结(1)(自动属性、out参数、对象初始化器、var和dynamic等)

一. 语法糖简介 语法糖也译为糖衣语法&#xff0c;是由英国计算机科学家彼得约翰兰达&#xff08;Peter J. Landin&#xff09;发明的一个术语&#xff0c;指计算机语言中添加的某种语法&#xff0c;这种语法对语言的功能并没有影响&#xff0c;但是更方便程序员使用。通常来说…

java不用插件播放媒体文件_java servlet不用插件上传文件:

展开全部import java.net.*;import java.io.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;public class SaveFileServlet extends HttpServlet{FileWriter savefile;String filename null;String value null;/*** Handles a POST request*/publ…

第八节:语法总结(2)(匿名类、匿名方法、扩展方法)

一. 匿名类 1. 传统的方式给类赋值&#xff0c;需要先建一个实体类→实例化→赋值&#xff0c;步骤很繁琐&#xff0c;在.Net 3.0时代&#xff0c;微软引入匿名类的概念&#xff0c;简化了代码编写&#xff0c;提高了开发效率。 匿名类的声明语法&#xff1a; var objnew {字段…

java 里面matches什么意思_Java Regex中的matches()和find()之间的区别

如果完整string匹配&#xff0c; matches()将只返回true。 find()会尝试find匹配正则expression式的子string中的下一个匹配项。 注意强调“下一个”。 这意味着&#xff0c;多次调用find()的结果可能不一样。 另外&#xff0c;通过使用find()你可以调用start()来返回子string匹…

第九节:委托和事件(1)(委托的发展历史、插件式编程、多播委托)

一. 委托的发展历史和基本用法 说起委托&#xff0c;每个人可能都会对他有不同的理解&#xff0c;结合实战中委托的使用&#xff0c;我对其理解是&#xff1a;委托和类一样&#xff0c;是用户的一个自定义类型&#xff0c;委托可以有参数、有返回值&#xff0c;委托的关键字是d…

java为什么不使用odbc_java jdbc和odbc的区别是什么?jdbc和odbc的关系是怎样的?

对于jdbc和odbc你都了解多少呢?今天要给大家讲到的就是jdbc和odbc之间的内容&#xff0c;一起来了解一下jdbc和odbc的区别以及关系是怎样的吧!下面先来给大家介绍一下jdbc和odbc之间的区别。总的来说&#xff0c;jdbc和odbc的区别可以划分成三大部分&#xff0c;一起来看看。一…

第十节:委托和事件(2)(泛型委托、Func和Action、事件及与委托的比较)

一. 泛型委托 所谓的泛型委托&#xff0c;即自定义委托的参数可以用泛型约束&#xff0c;同时内置委托Func和Action本身就是泛型委托。 将上一个章节中的Calculator类中的方法用自定义泛型委托重新实现一下。 1 public class Calculator22 {3 //传统解决方案一&am…