java安全

1 Provider称为提供者类

1.1 负责加密算法、密钥算法


1.2 jdk本身就有10个provider


security.provider.1=sun.security.provider.Sun

security.provider.2=sun.security.rsa.SunRsaSign

security.provider.3=sun.security.ec.SunEC

security.provider.4=com.sun.net.ssl.internal.ssl.Provider

security.provider.5=com.sun.crypto.provider.SunJCE

security.provider.6=sun.security.jgss.SunProvider

security.provider.7=com.sun.security.sasl.Provider

security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI

security.provider.9=sun.security.smartcardio.SunPCSC

security.provider.10=sun.security.mscapi.SunMSCAPI


常用的第三方的BouncyCastleProvider也是很强悍的,但是需要手动添加到环境


1.3 provider的结构大致如下: 

一个name

一个info

多个service

        一个service对应多个Algorithm:RSA AES MD5withRSA等


2 Security负责管理Provider

添加第三方provider

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());



3 Key所有密钥的顶层接口

3.1 生成一个key指定两个属性

(1)它使用什么算法:

        如AES、DES、RSA等


(2)它使用什么编码:

        密钥的码形式:X509、PKCS#8


3.2 下面接口方法可以窥伺Key结构

Key.getAlgorithm()返回算法名词:RSA

Key.getFormat返回编码格式名称:'PKCS#8'等

Key.getEncoded()返回密钥编码后的byte[],可以用base64编码后可见
        

3.3 三大接口继承自Key

SecretKey(对称加密顶层接口),Publickey\PrivateKey(非对称加密的顶层接口)


4 对称密钥生成

KeyGenerator kgen = KeyGenerator.getInstance("AES");

kgen.init(128, new SecureRandom(password.getBytes()));// 种子定了,random就定了

SecretKey secretKey = kgen.generateKey(); 


5 非对称密钥生成

5.1 KeyPair是非对称密钥的扩展

5.2 KeyPairGenerator生成密钥对

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");

keyPairGenerator.initialize(1024);

KeyPair keyPair = keyPairGenerator.generateKeyPair();

PrivateKey privateKey = keyPair.getPrivate();

PublicKey publicKey = keyPair.getPublic();


5.3 KeyFactory生成私钥(公钥流程一样,配置略有不同)

PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(btye[] encode);// 私钥特定编码后的btye[]

KeyFactory keyFactory = KeyFactory.getInstance("RSA");

PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);



6 SecureRandom 

为何在安全方便不能使用普通的Random?

为何在安全方便不能使用
普通的Random使用的是Linear Congruential Generator线性同余发生器,实际上这个随机数是可预测的,所以在安全领域,一般使用SecureRandom



7 Chiper 暗号

使用密钥对明文、密文实现具体的加密、解密过程。需要初始化模式

cipher.getIntance(String transformation)

transformation = “算法/工作模式/填充模式”,如AES/CBC/PKCS5Padding ,最简单为仅为 AES

ECB工作模式没有偏移量,CBC工作模式有便宜量

PKCS5Padding比PKCS7Padding效率高,PKCS7Padding可支持IOS加解密

对于对称加密

cipher.init(Cipher.DECRYPT_MODE, privateKey);// 对称加密

cipher.init(Cipher.ENCRYPT_MODE, privateKey);// 对称解密

对于非对称加密

cipher.init(Cipher.DECRYPT_MODE, publicKey);// 初始化公钥解密

cipher.init(Cipher.ENCRYPT_MODE, privateKey);// 初始化私钥加密

加密

byte[] 密文=cipher.doFinal(byte[] 明文)

解密

byte[] 明文=cipher.doFinal(byte[] 密文)


8 keySpec

密钥编码规范的顶层接口

keySpec  -> EncodedKeySpec(抽象) -> 两实现类(1)X509EncodedKeySpec 构建公钥编码规范(2)PKCS8EncodedKeySpec 构建私钥编码规范 

keySpec -> SecretKeySpec 兼容所有的对称加密密钥编码规范  。同时SecretKeySpec 又是SecretKey接口实现类

例如:SecretKeySpec key = new SecretKeySpec(keyStr.getBytes("utf-8"), "AES"); 注意aes的key的长度(二进制)只能是128/256位等

keySpec -> DESKeySpec 仅仅是DES编码规范


9 Signature 

封装了签名和验签,实际上也可以自己实现杂抽和非对称算法实现

(1)指定公钥和私钥

(2)指定签名算法:MD5withRSA等

签名

String info = "i am jack";

Signature signature = Signature.getInstance("MD5withRSA", new BouncyCastleProvider());

signature.update(info.getBytes("utf-8"));

byte[] signByte = signature.sign();

String sign = Base64.encodeBase64String(signByte);

验签:

String sign = "xhajklak";

String info = "i am jack";

Signature signature = Signature.getInstance("MD5withRSA", new BouncyCastleProvider());

signature.initVerify(publicKey);

signature.update(info.getBytes("utf-8"));

boolean status = signature.verify(Base64.decodeBase64(sign));


9 贴代码

//----------------签名-------------------


PemReader pemReader = new PemReader(new InputStreamReader(new FileInputStream("privkey.pem")));

PemObject pemObject = pemReader.readPemObject();

byte[] content = pemObject.getContent();

PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);

Provider provider = new BouncyCastleProvider();

Security.addProvider(provider);

KeyFactory factory = KeyFactory.getInstance("RSA","BC");

privateKey = factory.generatePrivate(privKeySpec);


String info = "i am jack";

String md5 = Base64.encodeBase64String(md5Digest.digest(info.getBytes("utf-8")));

Cipher cipher = Cipher.getInstance("RSA");

cipher.init(Cipher.ENCRYPT_MODE, privateKey);

byte[] signByte = Base64.decodeBase64(md5);

byte[] digestByte = cipher.doFinal(signByte);

String sign =  Base64.encodeBase64String(digestByte);


//--------------验签------------------


PemReader pemReader = new PemReader(new InputStreamReader(new FileInputStream("public.pem")));

PemObject pemObject = pemReader.readPemObject();

byte[] content = pemObject.getContent();

X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content);

Provider provider = new BouncyCastleProvider();

Security.addProvider(provider);

KeyFactory factory = KeyFactory.getInstance("RSA","BC");// BC是使用BouncyCastle的意思

PublicKey publicKey = factory.generatePublic(pubKeySpec);


String sign = "Vl7cDe1mdiT6BBGJOt9oXIigVh4=";

String info = "i am jack";

Cipher cipher = Cipher.getInstance("RSA");

cipher.init(Cipher.DECRYPT_MODE, publicKey);

byte[] signByte = Base64.decodeBase64(sign);

byte[] digestByte = cipher.doFinal(signByte);

String md5Temp = Base64.encodeBase64String(digestByte);


MessageDigest md5Digest = MessageDigest.getInstance("MD5");

String md5 = Base64.encodeBase64String(md5Digest.digest(info.getBytes("utf-8")));

if(md5Temp.equals(md5)){
// 验签成功
}


为何在安全方便不能使用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值