`
s103y
  • 浏览: 116716 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

使用Java开发和信息安全相关的程序(CA)

阅读更多

这里说的信息安全是相对于系统安全而言的,它更侧重于加密,解密,数字签名,验证,证书等等.而系统安全主要侧重于系统本身是否有安全漏洞,如常见的由于软件设计的不完善而导致的满天飞的缓冲区溢出等等.

Java语言中负责加密功能的部件是JCE(Java Crypto Extenstion),它使用开放式的思想,可以允许用户自己编写加密算法的具体实现的模块等.这些东西被称为JCE Provider,JCE的提供者.SUN公司本身提供了一些Provider.不过我推荐使用Bouncy Castle的Provider.原因是它实现的加密算法多,连比较新的椭圆曲线(ECC)算法都有了.去http://www.bouncycastle.org/可以找到你所希望的.Bouncy Castle除了提供Provider本身以外,还包括了一个S/MIME和一个open pgp 的jar包只有Provider本身是必要的,后两个包是方便你编程而提供的.例如有了S/MIME包后,你就不再需要为诸如"加密一个字符串或者一片文章然后签名"之类的很现实的应用程序写上一大堆代码了,只要引用S/MIME包中的某几个类,很快就可以搞定.而open pgp的存在,使你在用Java编写和PGP/GPG交互的程序时方便多了.

这次先写这么多了,下次开始具体讲把这些东西搞下来后怎么开始干活吧.我以我现在手头上正在做的事情告诉大家,如何做一个CA.

有了BC Provider,开CA,真的就是这么简单!

使用Java实现CA(一)

通过我昨天的文章大家应该已经清楚了,用Java写信息安全方面的程序需要做的准备工作.好了,现在假设你已经是一个对Java语言本身比较熟悉,能够用Java写一些程序的人,并且这些该下载的jar包已经下载好了,可以正式开工了.

在所有的此类程序的开头(无论是在类的构造函数中也好,在初始化函数中也好),都要先来上这么一句:Security.addProvider(new BouncyCastleProvider());将BouncyCaslte的Provider添加到系统中,这样以后系统在运行相关程序的时候调用的就是这个Provider中的加密算法.

然后我们就可以开始开CA了.首先,作为一个CA要有自己的一对公钥和私钥,我们先要生成这么一对.使用KeyPairGenerator对象就可以了, 调用KeyPairGenerator.getInstance方法可以根据要生成的密钥类型来产生一个合适的实例,例如常用的RSA,DSA等.然后调用该对象的initialize方法和generateKeyPair方法就可以产生一个KeyPair对象了.然后调用KeyPair对象中的相应方法就可以获取生成的密钥对中的公钥和私钥了.

有了公钥和私钥对以后,下面的一个很现实问题就是如何把它们储存起来.通常我们要对这些安全对象,如公钥,私钥,证书等先进行编码.编码的目的是为了把结构复杂的安全对象变成字节流以便存储和读取,如DER编码.另外,通常还把DER编码后的字节流再次进行base64编码,以便使字节流中所有的字节都变成可打印的字节.

在Java语言中,这些安全对象基本上都有getEncoded()方法.例如:

byte[] keyBytes = privateKey.getEncoded();

这样就把一个私钥进行了DER编码后的结果保存到一个byte数组中了.然后就可以把这个byte数组保存到任何介质中.如果有必要的话,可以使用BC Provider中的Base64编码解码器类进行编码,就像这样:

byte data[] = Base64.encode(keyBytes);

要从文件中读取私钥则应该这样:

PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyData);
KeyFactory kfac = KeyFactory.getInstance("RSA");
privateKey = kfac.generatePrivate(spec);

这里说明一下,对RSA私钥进行编码就会自动地按照PKCS8进行.因此读取的时候将包含编码的字节数组作为PKCS8EncodedKeySpec对象的构造函数的参数就可以生成一个该类型的对象.然后创建一个密钥工厂对象就可以按照要求生成一个RSA私钥了.很显然这里的keyData应该是和上面的 keyBytes内容相同.

为了提高系统的安全性,通常私钥在经过DER编码后,还会使用一个口令进行加密,然后再储存在文件系统中.在使用私钥的时候,如果没有正确的口令,是无法把私钥还原出来的.

保存证书和保存私钥类似.Certificate对象中也有一个getEncoded的方法.

这次就讲这些.大家应该可以把这些安全对象很熟练地从文件系统和内存之间来回地折腾了吧.这对以后实现CA是很重要的.下次我会讲一下证书中表示主体的方法:DN.

使用Java实现CA(二)


我们讲到如何生成密钥对,以及如何将诸如公钥,私钥,证书等这一类安全对象在文件系统和内存之间来回转换.这些是准备开CA的基本功,今天我们讲一下CA的基本原理以及如何使用主体名称结构DN(Distinguish Name)来表示每一个证书中的主体.

一份证书就是一个权威机构对一个主体的身份的确认的证明.即一份证书表示一个权威机构确认了一个主体就是它自己,而不是其它的冒名顶替者.主体可以是一个个人,也可以不是,例如,在需要安全服务的时候,需要为一台网站的服务器颁发证书,这种证书的主体就是一台服务器.签署证书的权威机构就叫做CA,该权威机构本身也是一个主体.权威机构通过对包含有待认证的主体的一系列信息的待签名证书"(TBS,to be signed)进行数字签名来表示该机构对它的认可.一份包含了待认证的主体的相关信息的TBS再加上CA使用自己的私钥进行签名产生的字节流放在一起, 就构成了一份标准的X509证书.

一个TBS中包含了以下这些主要信息:

证书的版本,通常是3(X509v3)

证书的序列号,RFC3280中规定,每个CA必须确保它颁发的每一份证书的序列号都是唯一的,并且序列号只能使用非负整数.

签发者(CA)的主体名称,一个DN对象.

证书的有效期,表示方法是两个时间值,表示了该证书从何时开始生效,何时开始作废.

待认证的主体的主体名称,也是一个DN对象.

待认证的主体的公钥,任何安全应用在确认完证书的有效性后,就可以开始使用该主体的公钥与之进行安全通信.

如果是X509v3证书,即版本号是3的话,后面还有一个证书扩展信息字段,可以在证书里面添加一些其它的信息.

下面我们来看一下表示主体的主体名称结构:DN.这个结就构是一个属性的集合.每个属性有属性名称和属性值.它的作用就是用来表示"我是谁",也就是说,这个证书到底是谁颁发给谁的,这个证书对应的公钥是谁拥有的.

通常使用一个字符串来表示DN结构,这种字符串说明了这种结构中的各个属性的类型和值:

C=CN;S=BeiJing;L=BeiJing;O=PKU;OU=ICST;CN=wolfenstein

这里C是国家和地区代码,S和L都是地区代码,S相当于省或者州这样的级别,L相当于城市级别,O是组织机构名称,OU是次级组织机构名称,CN是主体的通用名(common name).在这里,C,S,L等等属性的类型都是相对固定的,例如C一般就是用来表示国家和地区代码,在DN结构中还可以添加一些其它类型的信息,一般也都是以"xxx=xxx"这样来表示的.

下面我们来说明如何在Java语言中构造出一个主体名称对象.

BC Provider中使用X509Name对象来表示DN,构造一个X509Name的步骤大体如下:

先构造两个vector对象,用来表示属性名称和属性值:

Vector oids = new Vector();
Vector attributes = new Vector();

然后在oids这个用来表示属性名称的vector对象中将属性名称一个一个添加进去:

oids.addElement(X509Name.C);

......

oids.addElement(X509Name.CN);

X509Name对象里面有若干常量,例如上面的X509Name.C.还有X509Name.ST等等,都可以和上面举的例子对应起来.

然后将属性值添加到attributes对象中:

attributes.addElement("CN");

......

attributes.addElement("Wolfenstein");

最后就可以构造出一个X509Name对象:

X509Name SubjectDN = new X509Name(oids, attributes);

这样,我们的主体名称结构就确立起来了.

下次我们就可以讲关键的部分了,那就是如何用Java程序完成CA最重要的功能,签署证书.

使用Java实现CA(三)

前几次我已经基本上把如何做CA所需要的基础知识讲得差不多了,今天直接讲如何用Java程序来实现一个CA应该就不是什么太困难的事情了.

要做CA,第一步要准备好自己的证书和私钥.私钥如何从文件里面读取出来前面已经讲过了.从文件系统中读出证书的代码如下:

CertificateFactory certCF = CertificateFactory.getInstance("X.509");
X509Certificate caCert = certCF.generateCertificate(certBIS);

这里cerBIS是一个InputStream类型的对象.例如一个标准的X509v3格式的证书文件所形成的输入流.

第二步就是从用户那里获取输入,然后构造主体名称结构DN,如何构造DN上次已经说过了,如何从用户那里获取输入,这个不在本文讨论范围之内.

下一步就是获取用户的公钥,好和他所需要的证书对应起来.也有不少CA的做法就是在这里替用户现场生成一对密钥对,然后把公钥放到证书中签发给用户.这个应该看实际需要选择合适的方式.

现在一切信息都已经准备好了,可以签发证书了,下面的代码说明了这个过程:

//构造一个证书生成器对象

X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();

// 从CA的证书中获取签发者的主体名称(DN)
// 这里有一点小技巧,我们要把JCE中定义的
// 用来表示DN的对象X500Principal转化成在
// BC Provider中的相应的对象X509Name
// 先从CA的证书中读取出CA的DN进行DER编码
DERInputStream dnStream =
new DERInputStream(
new ByteArrayInputStream(
caCert.getSubjectX500Principal().
getEncoded()));
// 马上又从编码后的字节流中读取DER编码对象
DERConstructedSequence dnSequence =
(DERConstructedSequence)dnStream.readObject();
// 利用读取出来的DER编码对象创建X509Name
// 对象,并设置为证书生成器中的"签发者DN"
certGen.setIssuerDN(new X509Name(dnSequence));
// 设置好证书生成器中的"接收方DN"
certGen.setSubjectDN(subjectDN);
// 设置好一些扩展字段,包括签发者和
// 接收者的公钥标识
certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false,
createSubjectKeyId(keyToCertify));
certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false,
createAuthorityKeyId(caCert.getPublicKey()));
// 设置证书的有效期和序列号
certGen.setNotBefore(startDate);
certGen.setNotAfter(endDate);
certGen.setSerialNumber(serialNumber);
// 设置签名算法,本例中使用MD5hash后RSA
// 签名,并且设置好主体的公钥
certGen.setSignatureAlgorithm("MD5withRSA");
certGen.setPublicKey(keyToCertify);

// 如果以上一切都正常地话,就可以生成证书了
X509Certificate cert = null;
cert = certGen.generateX509Certificate(caPrivateKey);

这里是上面用到的生成签发者公钥标识的函数:

protected AuthorityKeyIdentifier createAuthorityKeyId(PublicKey pubKey)
{
AuthorityKeyIdentifier authKeyId = null;

try
{
ByteArrayInputStream bIn = new ByteArrayInputStream(pubKey.getEncoded());
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
(DERConstructedSequence)new DERInputStream(bIn).readObject());
authKeyId = new AuthorityKeyIdentifier(info);
}
catch (IOException e)
{
System.err.println("Error generating SubjectKeyIdentifier: " +
e.toString());
System.exit(1);
}

return authKeyId;
}

生成主体公钥标识的函数和上面的类似,把AuthorityKeyIdentifier替换成SubjectKeyIdentifier就可以了.

这里要注意的是,CA的公钥也是在一份证书里,这种证书的特点是签发者DN和接收者DN一样,也就是说,这种证书是CA自己给自己颁发的证书,也就是"自签名证书",它上面的公钥是CA自身的公钥,用来签名的私钥就是该公钥对应的私钥.一般每个CA都要有这么一份证书,除非该CA不是根CA,即它的权威性不是由它自己证明,而是由它的上级CA证明.但是,最后总归要有一个根CA,它为各个安全应用程序的用户所信赖.

到这里我们已经把CA最基本的功能如何用Java实现讲完了,下一次讲如何从PKCS#10格式证书请求文件中读取出用户信息,然后直接签发公钥.

使用Java实现CA(四)

前面几篇文章已经把如何用Java实现一个CA基本上讲完了.但是他们都有一个特点,就是用户的信息都是在现场获取的,不能做申请和签发相分离.今天我们要讲述的是PKCS#10证书请求文件.它的作用就是可以使申请和签发相分离.

PKCS#10证书请求结构中的主要信息包含了被签发者(证书申请者)的主体名称(DN)和他的公钥.因此一个CA在获取到一个PKCS#10证书请求后,就可以从中获取到任何和签发证书有关的信息,然后用它自己的私钥签发证书.

使用BC Provider在Java中构造一个证书请求格式的对象调用其构造函数即可,这个函数如下:

PKCS10CertificationRequest(java.lang.String signatureAlgorithm, X509Name subject, java.security.PublicKey key, ASN1Set attributes, java.security.PrivateKey signingKey)

它的参数是自签名算法,证书申请者的DN,证书申请者的公钥,额外的属性集(就是要申请的证书的扩展信息),申请证书者的私钥.申请证书者的私钥仅仅是用来进行一下自签名,并不出现在证书请求中,需要自签名的目的是保证该公钥确实为申请者所有.

调用该对象的getEncoded()方法可以将其进行DER编码,然后储存起来,该对象还有另一个构造函数:
PKCS10CertificationRequest(byte[] bytes)
这个构造函数的作用就是直接从储存的DER编码中把这个对象还原出来.

利用证书请求结构进行证书签发的代码如下,这里假设CSR是一个已经获取出来的PKCS10CertificationRequest结构:

PublicKey SubjectPublicKey = CSR.getPublicKey();
CertificationRequestInfo CSRInfo = CSR.getCertificationRequestInfo();
X509Name SubjectDN = CSRInfo.getSubject();
ASN1Set Attributes = CSRInfo.getAttributes();

这样,申请者的主体DN,申请者的公钥,申请者希望在证书扩展信息中填写的属性都得到了,剩下的事情就和用户在现场输入时一样了,其它的信息一般是申请者不能决定的.另外证书请求格式中有一样信息没有明确给出来,那就是证书的有效期,这个应该单独询问用户,或者用其它的方法保存起来.

分享到:
评论

相关推荐

    使用Java开发和信息安全相关的程序

    开发信息安全相关的Java程序,还需要熟悉各种加密和认证协议,如SSL/TLS、X.509证书、PKCS#7和PKCS#12等。此外,理解数字签名的工作原理,以及如何使用Java的`Signature`类进行签名和验证也是至关重要的。 总的来说...

    Java实现浏览器CA证书的签名和验证

    2. **创建自签名证书**:使用私钥和相关的证书信息,可以创建一个自签名的数字证书。这一步骤通常涉及`X509Certificate`和`X509CertificateBuilder`类。 3. **证书导入浏览器**:为了使浏览器能够信任这个自签名...

    Java-ca.rar_CA_DVB ca_ca java_java Ca_数字签名

    Java数字签名是Java平台中用于实现安全通信的重要技术,它在加密的基础上增加了验证信息完整性和来源可靠性的功能。在Java中,数字签名主要用于确保代码的完整性和防止篡改,同时也常用于身份验证和数据完整性保护。...

    usb.rar_USB KEY_java Ca_usb_证书

    总之,这个压缩包提供了一个与USB KEY和Java CA相关的程序,用于增强身份验证和数据安全。对于那些需要在安全环境中工作的开发者或IT专业人士来说,这是一个非常有用的技术资源。通过学习和理解这个程序,可以更好地...

    java_2868CA认证服务的方法和实现

    Java CA(Certificate Authority)认证服务是网络安全领域中的一个重要概念,它涉及到数字证书的颁发、管理和验证,用于确保网络通信的安全性。在这个主题中,我们将深入探讨Java如何实现CA认证服务,以及相关的具体...

    java加密小程序

    在这个程序中,我们可以探索如何在Java环境中实现数据的安全存储和传输,这对于任何软件开发来说都是至关重要的。下面,我们将深入讨论Java加密的相关知识点。 1. **Java加密基础**: Java提供了强大的加密库,如...

    CA证书接口用法

    北京数字证书认证中心已经完成了证书应用接口的产品化工作,并形成了自主知识产权、具有相关安全产品资质的Web信息安全系统BJCASecX软件。 在证书应用接口中,集成目标是指应用系统主管单位和开发单位需要完成的...

    信息安全大作业-CA系统的设计和实现源码(电子认证服务系统-数字证书数字签名python语言)+项目详细说明.7z

    信息安全大作业_CA系统的设计和实现源码(电子认证服务系统_数字证书数字签名python语言)+项目详细说明.7z CA代表Certificate Authority。也就是电子认证服务或机构,为电子签名相关各方提供真实性和可靠性验证,是...

    Java安全教程-创建SSL连接和证书Java开发Jav

    在Java开发过程中,理解并正确处理证书的生命周期管理也非常重要。例如,证书过期、撤销或被替换时,需要更新应用程序中的TrustStore。此外,对于自签名证书或内部CA签发的证书,可能需要添加到用户的TrustStore,...

    ejbca.rar_CA_EJBCA_ca java_ejbca制_rsa ca

    这个“ejbca.rar_CA_EJBCA_ca_java_ejbca制_rsa ca”压缩包显然包含了与构建和管理EJBCA相关的资源,特别是涉及到RSA加密算法和数字签名技术。 首先,我们要理解CA(Certificate Authority)是什么。CA是公钥基础...

    Java聊天室程序

    可能采用数据库来存储历史记录,使用线程安全的数据结构来管理用户和会话信息,同时使用异步编程模型来避免阻塞主线程。 在开发过程中,测试和调试也是至关重要的环节。单元测试可以帮助开发者验证各个模块的功能,...

    java一机一密实现代码

    在 `exportToJKS` 方法中,我们将证书从 BKS 导出到 JKS 格式,以便在其他 Java 应用程序中使用。 3. **创建 SSLSocketFactory**: `SSLSocketFactory` 是用于创建 SSL 或 TLS 安全套接层套接字的工厂类。在 `...

    JAVA 使用数字证书加密解密文件

    在IT领域,尤其是在网络安全和数据保护方面,...了解并掌握这些技术,对于开发安全的应用程序至关重要。在实际工作中,我们还需要关注Java的加密限制,如默认的密钥长度限制,以及可能需要的JCE无限制强度策略文件。

    java安全性编程教案(java)

    Java安全性编程是Java开发中的重要领域,特别是在网络应用技术中,确保代码安全是开发者必须面对的关键挑战。本教案将深入探讨Java平台的安全机制,通过实例讲解如何有效地进行安全性编程。 一、Java安全模型基础 ...

    Java安全体系在Web程序中的研究和应用

    ### Java安全体系在Web程序中的研究和应用 #### 1. 方案背景及意义 随着互联网技术的迅猛发展,Web程序已经成为人们日常生活中不可或缺的一部分,包括电子商务、电子政务、在线教育等多个领域。然而,互联网的开放...

    (Java实用系统开发指南(彭晨阳著)\电子认证

    在实际的Java系统开发中,理解并熟练使用电子认证技术对于开发安全的应用程序至关重要。这包括但不限于:设置HTTPS服务器、实现安全的通信协议、验证客户端的身份等。开发者需要熟悉KeyStore操作,知道如何加载、...

    Java安全_使用JavaAPI管理证书

    在Java编程环境中,安全是至关重要的一个方面,尤其是在网络通信和数据传输中。Java提供了丰富的API来管理和操作证书,以确保通信的安全性。本篇将深入探讨如何使用Java API进行证书管理,主要涉及两个核心概念:...

    基于JAVA的安全电子商务文档

    Java作为一种跨平台的编程语言,因其强大的安全特性而被广泛应用于电子商务系统开发。本文档将深入探讨基于Java的安全电子商务实现及其关键技术。 首先,Java的安全性源于其内置的安全模型。Java虚拟机(JVM)提供...

    java根证书

    理解Java根证书的概念、功能以及管理方式对于开发安全的Java应用程序至关重要。 根证书本质上是一份由证书颁发机构(CA)签署的数字证书,包含了CA的公钥和身份信息。当用户或系统收到一份未知来源的证书时,会通过...

Global site tag (gtag.js) - Google Analytics