RSA非对称加解密算法的使用

加密密钥和解密密钥相同时则称为对称加密。由于加密密钥和解密密钥相同,它们也被称为Shared Key。如AES等。

加密密钥(公钥)和解密密钥(私钥)不相同时则称为非对称加密,别称公钥密码。如RSA等。

非对称加密例子:

假设张三拥有的公钥Pu和私钥Pr,其公钥是公开的,谁想跟张三通信的话必须用张三的公钥Pu进行加密后传输给张三,张三用自己的私钥Pr解密后就能查看通信内容了。

RSA:建立在分解大数的困难度、公钥/私钥长度至少是1024bit。1英文字符=1字节=8bit位。

对称加密的优缺点:

1.高效

2.密钥交换问题

3.不如RSA的加密安全程度高,但是当选择256bit的AES时,仍然能胜任绝大多数的安全领域

非对称加密的优缺点:

1.安全性足够高

2.没有密钥交换的问题

3.效率低,对于大数据加密很慢

实际的保密会话应用场景:

1.基于高效的对称加密算法对会话进行加密

2.会话密钥实时产生并周期性变化

3.基于其他足够安全的方式进行会话密钥的传输和交换

针对上面的第3步,可以利用非对称加密方法来交换会话密钥:

1.产生实时随机的会话密钥

2.A使用对端B的公钥对产生的会话密钥进行加密并传递给对端B

3.对端B使用自己的私钥解密获取会话密钥

4.双方开始基于共享的会话密钥进行对称加密的保密会话通信

点对点通信使用上面的加解密方法进行通信,点对多的通信可以使用下面的方法进行广播:

5.B向任何人发消息时,发送的是使用自己私钥加密后的内容

6.任何人接收到消息后使用消息发送者B的公钥进行解密得到B广播的消息内容

非对称加密的两面性:

A使用B的公钥加密后,B可以使用自己的私钥进行解密;

B使用自己的私钥加密后,A可以使用B的公钥进行解密。

RSA加密算法实例:

public class RSA {

    private static RSA mInstance;
    private File mPublicKeyFile;
    private File mPrivateKeyFile;

    public static RSA getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new RSA(context);
        }
        return mInstance;
    }

    public RSA(Context context) {
        String path = context.getFilesDir().getAbsolutePath();
        mPublicKeyFile = createFile(path + "/publickey.dat");
        mPrivateKeyFile = createFile(path + "/privatekey.dat");
        generateKeyPair();
    }

    /**
     * 生成密钥对
     */
    private void generateKeyPair() {
        try {
            // RSA算法要求有一个可信任的随机数源
            SecureRandom sr = new SecureRandom();
            // 为RSA算法创建一个KeyPairGenerator对象
            KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
            // 初始化密钥长度
            kpg.initialize(1024, sr);
            // 生成密钥对
            KeyPair genKeyPair = kpg.genKeyPair();
            // 获取公钥
            PublicKey publicKey = genKeyPair.getPublic();
            // 保存公钥
            FileOutputStream fos = new FileOutputStream(mPublicKeyFile);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(publicKey);
            oos.close();
            // 获取私钥
            PrivateKey privateKey = genKeyPair.getPrivate();
            // 保存私钥
            FileOutputStream fos1 = new FileOutputStream(mPrivateKeyFile);
            ObjectOutputStream oos1 = new ObjectOutputStream(fos1);
            oos1.writeObject(privateKey);
            oos1.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 公钥加解密
     * isEncrypt: true是利用公钥加密,false是利用公钥解密
     */
    public byte[] encrypt(byte[] source, boolean isEncrypt) {
        byte[] result = null;
        try {
            // 获取公钥
            FileInputStream fis = new FileInputStream(mPublicKeyFile);
            ObjectInputStream ois = new ObjectInputStream(fis);
            RSAPublicKey publicKey = (RSAPublicKey) ois.readObject();
            ois.close();
            Cipher cipher = Cipher.getInstance("RSA");
            if (isEncrypt) {
                cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            } else {
                cipher.init(Cipher.DECRYPT_MODE, publicKey);
            }
            
            if (source != null) {
                // 加密
                result = cipher.doFinal(source);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 私钥加解密
     * isDecrypt: true是利用私钥解密,false是利用私钥加密
     */
    public byte[] decrypt(byte[] source, boolean isDecrypt) {
        byte[] result = null;
        try {
            // 读取私钥
            FileInputStream fis = new FileInputStream(mPrivateKeyFile);
            ObjectInputStream ois = new ObjectInputStream(fis);
            RSAPrivateKey privateKey = (RSAPrivateKey) ois.readObject();
            ois.close();
            Cipher cipher = Cipher.getInstance("RSA");
            if (isDecrypt) {
                cipher.init(Cipher.DECRYPT_MODE, privateKey);
            } else {
                cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            }
            if (source != null) {
                // 解密
                result = cipher.doFinal(source);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    private File createFile(String path) {
        File file = new File(path);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return file;
    }

}

调用:

try {
    String source = "哈哈嘻嘻的假短发接欧文多拉点开机费的";
    byte[] encrypt = RSA.getInstance(this).encrypt(source.getBytes("UTF-8"), true);
    String result = new String(RSA.getInstance(this).decrypt(encrypt, true), "UTF-8");
    System.out.println("zyf 使用公钥加密,私钥解密的结果: " + result);
    
    byte[] decrypt = RSA.getInstance(this).decrypt(source.getBytes("UTF-8"), false);
    result = new String(RSA.getInstance(this).encrypt(decrypt, false), "UTF-8");
    System.out.println("zyf 使用私钥加密,公钥解密的结果: " + result);
} catch (Exception e) {
    e.printStackTrace();
}

RSA的低效率特性导致即便是签名也不适合直接对原始信息进行签名,可以:

1.先计算出原始消息的MD5值

2.对MD5值进行基于非对称加密算法的签名

3.签名一般附着于原始消息尾部或头部一起发送

收到消息后,先用非对称加密算法对签名进行解密,解密后的MD5值与原始消息的MD5值进行比对,一致则认为消息没有被篡改。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值