RSA算法加密解密签名验签入门

2016-05-15 / 11 阅读 / Java

一些相关知识

1.对称加密算法(Symmetric-key algorithm)

1976年以前,所有的加密方法都是同一种模式:
  (1)甲方选择某一种加密规则,对信息进行加密;
  (2)乙方使用同一种规则,对信息进行解密。
这种加密模式有一个最大弱点:甲方必须把加密规则告诉乙方,否则无法解密。保存和传递密钥,就成了最头疼的问题。

2.非对称加密算法

(1)乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。
(2)甲方获取乙方的公钥,然后用它对信息加密。
(3)乙方得到加密后的信息,用私钥解密。

如果公钥加密的信息只有私钥解得开,那么只要私钥不泄漏,通信就是安全的。

看下百度百科对RSA算法的简介:

RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。1987年首次公布,当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。
RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。
今天只有短的RSA钥匙才可能被强力方式解破。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。但在分布式计算和量子计算机理论日趋成熟的今天,RSA加密安全性受到了挑战。

看来这种算法还是挺不错的,有必要了解一点的。不需要深入,最起码人家问起还能说点啥。不能啥都知道,那就尴尬了。

总结的来说RSA有以下一些用法:

  1. 加密
    就是把一段你看的懂的弄成鬼画符

  2. 解密
    就是把一段你看像鬼画符弄成你能看的懂得

  3. 签名
    就是把一段不想被其他人篡改内容,生成一段唯一字符

  4. 验签
    把那一段看到的内容重新生成唯一字符,与第3步生成的比较,一样就是验正成功,否则失败

具体用法

因为不需多深了解,所以代码还是有点粗糙的,不过能懂用法就行。

首先是密钥对的生成与存储
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        //公钥
        RSAPublicKey aPublic = (RSAPublicKey) keyPair.getPublic();
        //私钥
        RSAPrivateKey aPrivate = (RSAPrivateKey) keyPair.getPrivate();

        //把密钥对象对应的字节转为Base64字符存储
        System.err.println(new BASE64Encoder().encode(aPublic.getEncoded()));
        System.err.println(new BASE64Encoder().encode(aPrivate.getEncoded()));
密钥Base64字符转对象

        //这边省略掉部分字符
        String pubkey="******MIGfMA0GCSqGSIb3DQEBAQUAA*******";
        String prikey="*****MIICdgIBADANBgkqhkiG9w0BAQadQpzhqQAxw==***";

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

        //生成公钥对象
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(new BASE64Decoder().decodeBuffer(pubkey));
        PublicKey aPublic = keyFactory.generatePublic(x509EncodedKeySpec);

        //生成私钥对象
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(new BASE64Decoder().decodeBuffer(prikey));
        PrivateKey aPrivate = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
公钥KeySpec只能用X509EncodedKeySpec生成
私钥KeySpec只能用PKCS8EncodedKeySpec生成
否则会出现异常,原因没有深入研究,这边只记录下

 

加密
        String ming = "123456";
        byte[] bytes;
        {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE,aPrivate);
            //得到加密后的字节
            bytes = cipher.doFinal(ming.getBytes());
            System.out.println("--->"+new String(cipher.doFinal(ming.getBytes())));
        }
解密

        {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, aPublic);
            //把之前加密的字节还原回来
            System.out.println("--->"+new String(cipher.doFinal(bytes)));
        }
注意点
公钥和私钥都可以用来加密,只要保证其中一个加密,只能使用另一个解密
以上例子中使用的是私钥加密,公钥解密

 

签名
        Signature rsa = Signature.getInstance("SHA1WithRSA");
        rsa.initSign(aPrivate);
        rsa.update(ming.getBytes());
        byte[] sign = rsa.sign();
        System.err.println("签名结果----->  " + new BASE64Encoder().encode(sign));
验签
        Signature rsa = Signature.getInstance("SHA1WithRSA");
        rsa.initVerify(aPublic);
        rsa.update(ming.getBytes());
        boolean verify = rsa.verify(sign);
        System.out.println("验签结果"+verify);
相关推荐