Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RSAUtils代码存在问题 #1

Closed
LeadroyaL opened this issue May 14, 2019 · 4 comments
Closed

RSAUtils代码存在问题 #1

LeadroyaL opened this issue May 14, 2019 · 4 comments

Comments

@LeadroyaL
Copy link

src/main/java/com/immomo/rhizobia/rhizobia_J/crypto/RSAUtils.java

你好,在这个文件里出现了两处密码学的误用,如下:

第一处:

    public String keyAlgorithm = "RSA"; 

RSA加解密时候

  • 不使用Padding,在密文短的时候是可以攻击的(理论上);
  • 不使用分组模式,在密文较长(超过N 的长度)的时候是无法被加密的;

第二处:

    /**
     * @Description: 签名(私钥加密)
     * @Param: oriData 待签名数据
     * @return: byte[] 数字签名
     */
    public byte[] sign(String oriData) throws Exception {
        byte[] data = oriData.getBytes();
        // 对数据加密
        KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        byte[] encrypted = cipher.doFinal(data);
        return encrypted;
    }


    /**
     * @Description: 验签(公钥解密)
     * @Param: sign 签名
     * @return: String 待校验数据
     */
    public String verify(byte[] sign) throws Exception {
        // 对数据解密
        KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        byte[] original = cipher.doFinal(sign);
        String originalString = new String(original);
        return originalString;
    }

加签是对整个数据完整性的保证,输出一个长度较短的摘要,代码里的sign函数是用私钥把原文完全加密一遍,生成比明文还要长的数据,完全不是加签。

验签同样,按理说要返回true/false表示是否成功,这里返回明文,和我理解的不大一样。

建议把这个文件重写,不要误导后人。

@LeadroyaL LeadroyaL changed the title RSAUtils代码完全不对 RSAUtils代码存在问题 May 14, 2019
@momodememeda
Copy link
Contributor

momodememeda commented May 14, 2019

@LeadroyaL ,非常感谢你的宝贵意见! づ ̄ 3 ̄)づ
第一处问题我会尽快想办法解决,如已有正确方案或可参考方案,还请直接把代码贴出来,不要小气哟
第二处问题,我会按照true/false返回值,再重载一个函数,不知可否接受

@LeadroyaL
Copy link
Author

第一处:
https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html
RSA/ECB/PKCS1Padding (1024, 2048)
RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)
选取其中的一种即可,我自己实现时选的"RSA/ECB/OAEPWithSHA-1AndMGF1Padding"

第二处我的想法是在加签/验签函数里,主动把明文哈希,对该哈希进行加密/解密,这样包装起来更好用一点。
因为业务开发一般不懂密码学的使用,我看到很多的封装基本都是这个样子:“把明文传进来、返回一个简短的字符串,更加友好”;而不是将哈希传进来、进行加密。加签和加密是不一样的。

@momodememeda
Copy link
Contributor

@LeadroyaL 二处问题已修改。第二处没有封装哈希,在README中有提示用户可自行选用摘要算法;“返回一个简短的字符串”,排除使用压缩,返回的签名字符串大小是由RSA密钥的长度决定的,所以如果要返回简短的字符串,密钥长度应选择较短的。
如果仍有问题,还恳请继续指出

@momodememeda
Copy link
Contributor

momodememeda commented May 27, 2019

@LeadroyaL ,最近更新了如下三点内容:
1、源码所用的signature类中,已经封装了摘要算法,所以可以不必再生成摘要
2、RSA加解密时,明文是有长度限制的,明文字符串限制长度 = 密钥长度(byte) - padding占用大小(byte)
padding大小如下:
RSA/ECB/PKCS1Padding or RSA : 11
RSA/ECB/OAEPWithSHA-1AndMGF1Padding : 42
RSA/ECB/OAEPWithSHA-256AndMGF1Padding : 66
于是,新增加了encryptWithouLimit/edecryptWithoutLimit方法,摆脱明文长度的限制
3、新增加了ECDSA加验签方法,比RSA更快、签名更短等等,可参考如下:
https://blog.cloudflare.com/ecdsa-the-digital-signature-algorithm-of-a-better-internet/

如有疑问恳请继续指出,如无疑问该issue将于本周关闭,也可通过邮件联系projectone@immomo.com

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants