Java签名/证书机制
java签名/证书机制,可以保障使用者,安全地调用外部提供的jar,防止你信任的jar被篡改。
首先,java的签名,必须是基于jar包的。也就是说,你必须将你要提供的class,打包到jar里。
然后,通过 java 提供的签名工具(jarsigner)对jar包进行签名,发布。
签名原理:
使用非对称算法,生成一对公钥/私钥。
证书
证书是在签名基础上,对签名值,再进一步做一次加密。而这次加密使用的私钥和公钥都是证书机构提供的。
这种方式,是为了防止,有些恶意用户,在公钥发到你手上前,就对其做了手脚,然后再发一个动过手脚的jar给你,用动过手脚的公钥解动过手脚的jar包,是可以解开的。
而使用证书后,它会对已经加密的签名值,再做一层加密,这样,到你手里,你只需要通过证书机构的公钥进行解密,然后再用jar包发布者的公钥解密就行了。(只能在一定程度上,提供一些安全性)
1.带有私钥的证书
由PublicKey Cryptography Standards #12,PKCS#12标准定义,包含了公钥和私钥的二进制格式的证书形式,以pfx作为证书文件后缀名。
2.二进制编码的证书
证书中没有私钥,DER编码二进制格式的证书文件,以cer作为证书文件后缀名。
3.Base64 编码的证书
证书中没有私钥,BASE64编码格式的证书文件,也是以cer作为证书文件后缀名。
由定义可以看出,只有pfx格式的数字证书是包含有私钥的,cer格式的数字证书里面只有公钥没有私钥。
在pfx证书的导入过程中有一项是“标志此密钥是可导出的。这将您在稍候备份或传输密钥”。一般是不选中的,如果选中,别人就有机会备份你的密钥了。如果是不选中,其实密钥也导入了,只是不能再次被导出。这就保证了密钥的安全。
如果导入过程中没有选中这一项,做证书备份时“导出私钥”这一项是灰色的,不能选。只能导出cer格式的公钥。如果导入时选中该项,则在导出时“导出私钥”这一项就是可选的。
如果要导出私钥(pfx),是需要输入密码的,这个密码就是对私钥再次加密,这样就保证了私钥的安全,别人即使拿到了你的证书备份(pfx),不知 道加密私钥的密码,也是无法导入证书的。相反,如果只是导入导出cer格式的证书,是不会提示你输入密码的。因为公钥一般来说是对外公开的,不用加密
pfx-名词释义
公钥加密技术12号标准(PublicKey Cryptography Standards #12,PKCS#12)为存储和传输用户或服务器私钥、公钥和证书指定了一个可移植的格式。它是一种二进制格式,这些文件也称为PFX文件。
CER- 数字证书的原理
数字证书采用公钥体制,即利用一对互相匹配的密钥进行加密、解密。每个用户自己设定一把特定的仅为本人所知的私有密钥(私钥),用它进行解密和签名;同时设定一把公共密钥(公钥)并由本人公开,为一组用户所共享,用于加密和验证签名。当发送一份保密文件时,发送方使用接收方的公钥对数据加密,而接收方则使用自己的私钥解密,这样信息就可以安全无误地到达目的地了。通过数字的手段保证加密过程是一个不可逆过程,即只有用私有密钥才能解密.在公开密钥密码体制中,常用的一种是RSA体制。
用户也可以采用自己的私钥对信息加以处理,由于密钥仅为本人所有,这样就产生了别人无法生成的文件,也就形成了数字签名。采用数字签名,能够确认以下两点:
(1)保证信息是由签名者自己签名发送的,签名者不能否认或难以否认;
(2)保证信息自签发后到收到为止未曾作过任何修改,签发的文件是真实文件。
CER-数字证书
是数字形式的标识,与护照或驾驶员执照十分相似。数字证书是数字凭据,它提供有关实体标识的信息以及其他支持信息。数字证书是由成为证书颁发机构(CA)的权威机构颁发的。由于数字证书有证书权威机构颁发,因此由该权威机构担保证书信息的有效性。此外,数字证书只在特定的时间段内有效。
数字证书包含证书中所标识的实体的公钥(就是说你的证书里有你的公钥),由于证书将公钥与特定的个人匹配,并且该证书的真实性由颁发机构保证(就是说可以让大家相信你的证书是真的),因此,数字证书为如何找到用户的公钥并知道它是否有效这一问题提供了解决方案。
PKCS 全称是Public-Key Cryptography Standards ,是由 RSA 实验室与其它安全系统开发商为促进公钥密码的发展而制订的一系列标准,PKCS目前共发布过15 个标准。 常用的有:
PKCS#7 Cryptographic Message Syntax Standard
PKCS#10 Certification Request Standard
PKCS#12 Personal Information Exchange Syntax Standard
X.509是常见通用的证书格式。所有的证书都符合为PublicKey Infrastructure (PKI) 制定的ITU-T X509 国际标准。
密钥库文件格式【Keystore】
格式 | 扩展名 | 描述 | 特点 |
JKS | .jks/.ks | 密钥库的Java实现版本 provider为SUN | 密钥库和私钥用不同的密码进行保护 |
JCEKS | .jce | 密钥库的JCE实现版本 provider为SUN JCE | 相对于JKS安全级别更高 保护Keystore私钥时采用 TripleDES |
PKCS12 | .p12/.pfx | 个人信息交换语法标准 | 包含私钥、公钥及其证书 密钥库和私钥用相同密码进行保护 |
BKS | .bks | 密钥库的BC实现版本 provider为BC | 基于JCE实现 |
UBER | .ubr | 密钥库的BC更安全实现版本 provider为BC |
|
证书文件格式【Certificate】
格式 | 扩展名 | 描述 | 特点 |
DER | .cer/.crt /.rsa | 用于存放证书 | 不含私钥、二进制 |
PKCS7 | .p7b/.p7r | 【PKCS #7】 加密信息语法标准 | p7b以树状展示证书链,不含私钥p7r为CA对证书请求签名的回复,只能用于导入 |
CMS | .p7c/.p7m/.p7s | Cryptographic Message Syntax | p7c只保存证书 p7m:signature with enveloped data p7s:时间戳签名文件 |
PEM | .pem | Printable Encoded Message | 该编码格式在RFC1421中定义,其实PEM是【Privacy- Enhanced Mail】的简写,但他也同样广泛运用于密钥管理 ASCII文件 一般基于base 64编码 |
PKCS10 | .p10/.csr | PKCS #10公钥加密标准Certificate Signing Request | 证书签名请求文件 ASCII文件 CA签名后以p7r文件回复 |
SPC | .pvk/.spc | Software Publishing Certificate | 微软公司特有的双证书文件格式,经常用于代码签名,其中 1、pvk用于保存私钥 2、spc用于保存公钥 |
一个web应用如果需要提供以https的方式访问的服务的话,我们需要一个数字证书,这个证书的配置是在apache的配置文件或者其他web容器的配置文件中进行配置的。当然这个可以保存在keystore中。
我们自己的应用中通常所说的keystore或者truststore主要是针对于应用本身的需求来的。
keystore和truststore从其文件格式来看其实是一个东西,只是为了方便管理将其分开
keystore中一般保存的是我们的私钥,用来加解密或者为别人做签名
truststore中保存的是一些可信任的证书,主要是java在代码中访问某个https的时候对被访问者进行认证的,以确保其实可信任的。
truststore是必须的,如果我们没有显式的指定,那么java会默认指定为$JAVA_HOME/lib/security/cacerts这个文件。
双向SSL认证,服务器必须要信任客户端证书,因此,必须把客户端证书添加为服务器的信任认证中心,即$JAVA_HOME/lib/security/cacerts 这个文件
1)KeyStore:其中保存服务端的私钥
2)TrustKeyStore:其中保存客户端的授权证书
如果要指定的话,可以在java的参数中进行指定
-Djavax.NET.ssl.keyStore=clientKeys
-Djavax.net.ssl.keyStorePassword=password
-Djavax.Net.ssl.trustStore=clientTrust
-Djavax.net.ssl.trustStorePassword=password
Public class KeyStore extends Object
此类表示密钥和证书的存储设施。
KeyStore 管理不同类型的条目。每种类型的条目都实现 KeyStore.Entry 接口。提供了三种基本的 KeyStore.Entry 实现:
*KeyStore.PrivateKeyEntry
此类型的条目保存一个加密的PrivateKey,可以选择用受保护格式存储该私钥,以防止未授权访问。它还随附一个相应公钥的证书链。给定条目使用私钥和证书链进行自验证(self-authentication)。应用此验证的包括软件发布组织,它们将JAR 文件签名为发布和/或许可软件的一部分。
*KeyStore.SecretKeyEntry
此类型的条目保存一个加密的SecretKey,可以选择用受保护格式存储该密钥,以防止未授权访问。
*KeyStore.TrustedCertificateEntry
此类型的条目包含一个属于另一方的单个公钥Certificate。它被称为可信证书,因为keystore 的所有者相信证书中的公钥确实属于该证书的subject(所有者)所标识的身份。此类型的条目可用于验证其他方。
KeyStore 中的每一条目都用 “alias” 字符串标识。对于私钥及其关联的证书链,这些字符串用于区分实体验证自身可以采用的不同方式。例如,实体可以使用不同的证书授权或不同的公钥算法来验证自身。
别名是否区分大小写与实现有关。为了避免出现问题,建议不要在KeyStore 中使用只有大小写区别的别名。
在这里没有指定keystore 是否是持久性的,也没有指定keystore 是持久性时所使用的机制。这允许使用各种技术保护敏感的(例如,私有的或秘密的)密钥。一种选择是使用智能卡或其他集成加密引擎(SafeKeyper),也可以(以各种格式)使用文件之类更为简单的机制。
请求KeyStore 对象的典型方式包括使用默认类型和提供一个特定的keystore 类型。
* 使用默认类型:
KeyStore ks =KeyStore.getInstance(KeyStore.getDefaultType());
系统将返回默认类型的keystore 实现。
Java KeyStore的类型
JKS和JCEKS是Java密钥库(KeyStore)的两种比较常见类型(PKCS12,BKS,UBER)
KeyStore ks = KeyStore.getInstance("JKS");
必须先加载keystore 才能对其进行访问,一旦加载了 keystore,就能够从keystore 读取现有条目,或向keystore 写入新条目:
KeyStore ks =KeyStore.getInstance(KeyStore.getDefaultType());
char[] password = "pwd123".toCharArray();
java.io.FileInputStream fis = null;
try {
fis = newjava.io.FileInputStream("d:/certA.p12");
ks.load(fis, password);
// get myprivate key
KeyStore.PrivateKeyEntry pkEntry
=(KeyStore.PrivateKeyEntry)ks.getEntry("privateKeyAlias", password);
PrivateKeymyPrivateKey = pkEntry.getPrivateKey();
} finally {
if (fis !=null) {
fis.close();
}
}
// save my secret key
javax.crypto.SecretKey mySecretKey;
KeyStore.SecretKeyEntry skEntry
= newKeyStore.SecretKeyEntry(mySecretKey);
ks.setEntry("secretKeyAlias", skEntry, newKeyStore.PasswordProtection(password));
// store away the keystore
java.io.FileOutputStream fos = null;
try {
fos = newjava.io.FileOutputStream("newKeyStoreName");
ks.store(fos,password);
} finally {
if (fos !=null) {
fos.close();
}
}
注意,可以使用相同的密码加载keystore、保护私钥条目、保护秘密密钥条目以及存储keystore(如上文示例代码所示),也可以使用不同的密码或其他保护参数。
public class KeyReader {
public static voidmain(String[] args) throws Exception{
// Open aninput stream on the keystore file
StringcerFileName = "d:/certA.cer";
Stringp12FileName = "d:/certA.p12";
StringpfxPassword = "openssl";
InputStream fis= new FileInputStream(p12FileName);
// Create akeystore object
KeyStorekeyStore = KeyStore.getInstance("PKCS12", "BC");
// Load thefile into the keystore
keyStore.load(fis, pfxPassword.toCharArray());
StringaliaesName = "abcd";
PrivateKeypriKey = (PrivateKey) (keyStore.getKey(aliaesName, null));
System.out.println("private key:/n" + priKey);
// public key
InputStream is= new FileInputStream(cerFileName);
CertificateFactorycf = CertificateFactory.getInstance("x509");
CertificatecerCert = cf.generateCertificate(is);
System.out.println("public key:/n" + cerCert);
}
}
KeyManagerFactory
此类充当基于密钥内容源的密钥管理器的工厂。每个密钥管理器管理特定类型的、由安全套接字所使用的密钥内容。密钥内容是基于KeyStore 和/或提供程序特定的源。
可以使用ssl.KeyManagerFactory.algorithm 安全性属性配置缺省算法。
通常,对于JSSE 而言,KeyStore中的每个证书都需要具备与KeyStore 本身相同的密码。自己构造 KeyManagerFactory
可以克服这个限制。
public interface X509KeyManager extends KeyManager
此接口的实例管理使用哪一个基于X509 证书的密钥对来验证本地的安全套接字。
在安全套接字协商期间,实现调用此接口中的方法来完成下面的工作:
* 确定基于现有标准进行协商可以使用的别名集合,
* 选择基于现有标准的最好的别名
* 为指定别名获取相应的密钥材
CertificateFactory
提供用于解析和管理证书、证书撤消列表(CRL) 和证书路径的类和接口。