机密性(Confidentiality)
机密性需求必须考虑的阶段
- 传输时
- 处理时
- 存储时
机密性的密码学应用
对称式加密
指加密与解密时,使用同一把密钥的加密方式。优点是速度非常快,相对于非加密式而言,约是100~1000倍快。缺点如下
- 除了传输密文,还需要传输密钥,安全性没有很好的保障
- 每增加一个接收方,就必须多一把密钥,造成密钥的管理困难
非对称式加密
指加密与解密时,使用不同的密钥,但公钥与私钥是配对的。非对称加密解决了对称加密的2个缺点。
HTTPS协议综合对称式加密与非对称式加密
加密应用应该遵守的原则有
- 使用公开的,国际机构认证的,且未遭破解的加密算法,不使用自行创建的加密方式
- 使用该加密方式支持的最大长度
- 密钥保存是关键,且应该定期更换密钥
HTTPS加密协议与服务器A的建立连线的交握过程
- 浏览器向服务器A要求服务器凭证 Certificate,其中包含服务器的公钥 (非对称式)
- 服务器回传凭证 包含公钥
- 浏览器验证服务器凭证合法性,若通过则产生一把一次性的,只使用这次连线的对称式密钥 (称之为Session Key)
- 使用服务器提供的公钥将Session Key加密成密文,传输给服务器端
- 服务器用密钥将密文解开,取得Session Key
- 后续双方传输的资料内容就使用Session Key进行加密和解密
Tomcat开启HTTPS
修改Tomcat的server.xml文件,将Connector的一段做如下修改
<Connector protocol="org.apache.coyote.http11.Http11NioProtocol" port="443" maxThreads="200" scheme="https" secure="true" SSLEnabled="true" keystoreFile="%HOME%/.keystore" keystorePass="changeit" sslProtocol="TLSv1.2" sslEnabledProtocols="TLSv1.1,TLSv1.2" clientAuth="false"/>
参数说明
- port
协定开启的端口,HTTPS通常使用443 - maxThreads
代表最高需要启动多少的线程进行服务,可以维持预设值 - scheme
决定调用request.getScheme()方法时的返回值,建议设置为https - secure
代表开启request.isSecure()这个方法,透过这个方法可以得知目前HTTP会谈连线Session是否为安全通道连线,建议设置为true - SSLEnabled
是否启用SSL/TLS协议,需设定为true - keystoreFile
HTTPS协议中服务器端所要使用的非对称式加密私钥对的实际档案位置。Tomcat支持的文件格式为JKS,PKCS11,PKCS12三种。其中JKS是Java标准中存放密钥的自定义格式。 - keystorePass
产生上述档案时设置的密码 sslProtocol
默认启用的SSL版本。Tomcat版本 SSL版本 7以上 建议设置TLSv1.2。此时默认启用的SSL版本有TLSv1.2,TLSv1.1,TLSv1,SSLv3(按版本由新到旧排序) 6版本 建议设置TLSv1.1。此时默认启用的SSL版本有TLSv1.1,TLSv1,SSLv3 - sslEnabledProtocols
强制指定可以使用哪些SSL版本。举例,当sslProtocol参数设定为TLSv1.2时,客户端浏览器仍然可以选用SSLv3,TLSv1,TLSv1.1,TLSv1.2等。 - clientAuth
是否进行客户端凭证验证
传输加密
Java中的传输加密标准为JSSE (Java Secure Socket Extension),其提供了API让Java开发者能够很容易的使用SSL/TSL技术。
Java的双向传输:传输双方,客户端与服务器端都有各自的KeyStore和TrustStore。服务器端的KeyStore用来存放自己本身的密钥对(包含私钥,公钥和凭证),TrustStore用来存放默认信任的客户端的凭证。客户端的KeyStore用来存放客户端自己本身的密钥对,TrustStore用来存放默认信任的服务器端凭证。
存储加密
Java 8版本已内建BASE64 Encoder和Decoder,可使用如下方法
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class Main {
public static void main(String[] args) {
try {
Base64.Encoder encoder = java.util.Base64.getEncoder();
Base64.Decoder decoder = java.util.Base64.getDecoder();
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
SecretKey key = keyGenerator.generateKey();
byte[] origData = "This String will be encrypt".getBytes("UTF-8");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptBin = cipher.doFinal(origData);
String keyString = encoder.encodeToString(key.getEncoded());
System.out.println(" Secret Key : " + keyString);
String encryptText = new String(encoder.encode(encryptBin));
System.out.println("Encrypt Text:" + encryptText);
SecretKeySpec secretKeySpec = new SecretKeySpec(decoder.decode(keyString), "AES");
Cipher decryptCipher = Cipher.getInstance("AES");
decryptCipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
byte[] decryptText = decryptCipher.doFinal(decoder.decode(encryptText));
System.out.println("Decrypt Text:" + new String(decryptText));
} catch (Exception e) {
e.printStackTrace();
}
}
}
目前Java标准版本中密码学应用(Java Cryptography Extension)的预设强度都被加以限制,不准许开发者使用各加密算法的最大的密钥长度。而只要在Oracle官网下载JDK时,同意该页面的一个选项 Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files for JDK/JRE 7。即可下载UnlimitedJCEPolicyJDK7.zip,解压缩后可得local_policy.jar 和 US_export_policy.jar两个文件,将其放置于$JRE_HOME/lib/security文件夹下,取代原有的文件即可。
机密性与OWASP
- 发生原因
- 最常见的是未加密敏感数据
- 使用脆弱的密钥管理方式,脆弱的加密算法和不够高的密钥长度
- 常见种类
- 敏感资料传输未使用加密通道。密码等敏感数据未使用加密,或未加salt(即密码加盐操作)
- 威胁来源
- 考虑谁可以存取资料,包含于传输过程,存储时,甚至备份后
- 攻击困难度
- 高,攻击者通常不通过暴力破解密码,而是通过窃取密钥,或是中间人攻击(man in the middle),或趁传输前后,存储前后,即密码还是明文时窃取
- 散播性
- 低,该弱点不具有散播性
- 可侦测性
- 中,必须全面考虑敏感数据的生命周期中各阶段的保护措施
- 技术面影响
- 高,依赖于保护措施
- 商业面影响
- 高
- 高
本博文是学习笔记,参考对象是蔡宗霖的《Java网站安全防护实务手册【软体开发安全技术的九大黄金准则】》