优点: 算法公开、计算量小、加密速度快、加密效率高
缺点:加解密密钥是一个,密钥如何安全保存是个难题,或者说,是潜在的风险点
对应密钥和公钥,使用密钥加密,通过公钥解密,反之也是
优点:安全,公钥可以放出,只要保存好私钥就好了
缺点:速度较慢
DES由于key不能安全保存,在公开发行的数据或文件,只能用RSA,但是RSA加密效率不行,而且对于很多非机密数据,我们其实不需要绝对的加密隐藏,只需要有机制保证其在传输过程中不被修改即可,这就需要数字签名了
数字签名步骤:
接受方在收到后,先用证书里的公钥对数字签名解密,接着使用同样的hash算法生成数据的hash值,再与解密后的数据对比,如果一致,说明数据没被修改过
证书包含如下信息:
证书的有效性验证,在拿到证书后,会通过证书发行机构的RSA公钥对证书签名数据解密,然后再用相同的hash算法,生成1+2的hash摘要,再跟解密后的指纹数据对比,如果是一致的,说明证书是有效的,再根据证书中拥有者的信息,来判定证书来源的正确性
通过上面我们可以知道,只要证书发行结构是值得信任的,那证书的完整性就是值得信任的,那对应的证书拥有者和公钥数据,就不存在中途被调包的风险,那数据在整个传输过程就是绝对安全的
证书文件格式一般都为 X509
什么是自签名证书,就是证书签名数据的生成,使用了个人的RSA私钥生成的,这会有两个风险:
所以,自签名证书,可以在学习的时候用用,正式的业务上,必须使用由权威结构颁发的证书,这就是CA证书的由来
CA证书在对客户证书签名时,客户首先提交待签名的证书,CA机构会验证客户信息的正确性和唯一性,然后再基于CA机构的RSA私钥对客户证书签名,生成CA证书
一般浏览器和操作系统,都会保持有CA的根证书,所以默认就可以对客户的CA证书做有效性验证
CA证书有3类:
添加intermediates颁发机构,是为了增加安全性,毕竟增加几级缓冲,让root私钥守在底处,让intermediates去面对各个客户,出问题的概率会大大的降低,万一某个intermediates出问题了,也只需要解除这个intermediates的信任就行了
证书链的原理也很简单,就是end-user可以通过intermediates来做证书校验,intermediates证书,也可以通过另一个intermediates校验,只要这个校验链,最终走到root根证书就行了,只要这个证书链上的证书,全部校验通过,那end-user的证书,就是可信的,反之,中途的任何一个校验不过,证书链中断,end-user不可信
如果你的CA证书是通过intermediates颁发的,有一点需要注意,就是接受校验方,是否拥有intermediates证书,因为CA根证书,就像上面说的浏览器和系统底层,都是预置的,如果intermediates没有,会导致链式校验中断,如果是https,需要在服务端做intermediates下载相关信息的配置
JKS(JavaKeysotre)格式和PFX(PKCS12)格式,是最常见的SSL证书格式文件,可以包含完整的证书密钥对,证书链和信任证书信息。
android源自java,所以一般都用JKS,ios则为.p12, PKCS12是行业标准格式,现在android生成.jks时,也会提示转换成PKCS12
两种格式得读取,都可以通过Java得 KeyStore来完成,具体代码参考#证书指纹#内的代码
基于证书内部数据生成,作为证书的标识,可以通过如下代码获取:
String jksPath = ""; //jks file path
String jksPassword = ""; // jks keyStore password
String certAlias = ""; // cert alias
String certPassword = ""; // cert password
KeyStore keyStore = null;
try {
keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream(jksPath), jksPassword.toCharArray());
PrivateKey privateKey = (PrivateKey) keyStore.getKey(certAlias, certPassword.toCharArray());
X509Certificate cert = (X509Certificate) keyStore.getCertificate(certAlias);
PublicKey publicKey = keyStore.getCertificate(certAlias).getPublicKey();
//证书的encoded值的md5,即为指纹
System.out.println("11 = " + shaEncode(cert.getEncoded()));
} catch (KeyStoreException e) {
}
所以,证书内部的任何参数变了,对应的encoded值肯定会变,对应的指纹数据也会变
还可以通过如下命令查看证书数据:
keytool -list -keystore debug.keystore
keytool -printcert -file META-INF/CERT.RSA
安装包在发布前,必须使用上述所说得SSL证书签名,android是.jks文件,ios则是.p12,目的当然也是上面说得:
由于android用的证书都是开发者自行创建并签名的自签名证书,所以系统安装时就无法对安装包得来源校验,只能利用证书的唯一性,针对证书指纹得对比,来避免app被非法替代安装
Android的V1和V2签名,原理是一致的,不同的是,签名数据和证书存放位置的不同:
哪个好?肯定是V2,V1由于META-INF目录下是不做校验的,所以发布包解压后,可以随便往这个目录下扔东西,还有,V1是基于zip内每个文件生成hash的,读取文件时,会做二次校验,会存在一部分的性能损耗
V2直接对整包做校验,发布后,就不能做任何修改了,而且读取文件时也不需要二次校验,所以性能会好点
IOS由于证书是经过苹果官方认证签名的,证书,开发者账号等等信息都存在苹果服务器,如果谁对app二次打包,安装时会校验失败
简单点说就是,android是自签名证书,可以二次打包后安装,前提是系统没有冲突得应用存在,ios由于是官方得签名证书,无法二次打包,因为安装得时候,系统会做证书信息校验
java读取jks公钥私钥
https://www.jianshu.com/p/a3b3cca98b06
Android V1及V2签名原理简析
http://www.jintiankansha.me/t/pNV38Zd4Ne
常见数字证书类型和代码解析
https://www.cnblogs.com/xq1314/archive/2017/12/05/7987216.html