java RSA算法(一)

来源:互联网 发布:饥荒联机内存优化mod 编辑:程序博客网 时间:2024/06/07 02:10

RSA加密是非对称加密,密钥对分公钥与私钥。公钥是用来给别人加密的。但是呢,java生成的publicKey的getEncode方法返回的是java格式的公钥,其它平台是认识不了的。
例如生成512的公钥:
305C300D06092A864886F70D0101010500034B003048024100925FC3FC103F6E2209E77D8FAF59B48DE06AE86471CDD5D5A4FCA6A06070C38578F49444A73222A9B3DAFC8C71C2BE14ECDA5EDA0667BA91182CCB3546BB85AF0203010001
这个明显不止64个bytes。我们今天就说一下这个。
先看段生成公钥的代码:

    public static TKeyPair RSAinitKey(int Length) throws Exception {          KeyPairGenerator keyPairGen;            keyPairGen = KeyPairGenerator                      .getInstance("RSA");            keyPairGen.initialize(Length);              KeyPair keyPair = keyPairGen.generateKeyPair();              X509EncodedKeySpec keySpec=new X509EncodedKeySpec(keyPair.getPublic().getEncoded());            // X509EncodedKeySpec priKeySpec=new X509EncodedKeySpec(keyPair.getPrivate().getEncoded());             KeyFactory keyFactory=KeyFactory.getInstance("RSA");              RSAPublicKey publickey=(RSAPublicKey) keyFactory.generatePublic(keySpec);            //PrivateKey privatekey=keyFactory.generatePrivate(priKeySpec);            return new TKeyPair(keyPair.getPrivate().getEncoded(),publickey.getEncoded());      }
    private static void test3() {        try {            TKeyPair keypair = CertificateUtil.RSAinitKey(512);            System.out.println("私钥:"+CertificateUtil.bytesToHexString(keypair.getPriKey()));            System.out.println("公钥:"+CertificateUtil.bytesToHexString(keypair.getPubKey()));            RSAPublicKey pubKey = (RSAPublicKey) CertificateUtil.getPublicKey(keypair.getPubKey());            System.out.println("公钥模数:"+CertificateUtil.bytesToHexString(pubKey.getModulus().toByteArray()));            System.out.println("公钥指数:"+CertificateUtil.bytesToHexString(pubKey.getPublicExponent().toByteArray()));            PrivateKey priKey = CertificateUtil.getPrivateKey(keypair.getPriKey());            byte[] enData = CertificateUtil.encrypt(pubKey, hello.getBytes());            byte[] out = CertificateUtil.decrypt(priKey, enData);            System.out.println(new String(out));        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }

测试一下,看一下打印结果:

私钥:30820155020100300D06092A864886F70D01010105000482013F3082013B020100024100B06EE9C5F7923031F313AABA8E9E5F43D35CEF2CEC77C73203D7CB329451E65E467ADDC5DEA1524D7E36625A09A61E38368215615E5670EB43C925E4AE73BA83020301000102407B1E5AE9F7D23EE98C4BCC16F55114FF7AAE5E8505DAABD97E0F07501B6A6F8B6EDFDF873E4117781A4ED845F96322BDF46FB1D3284A75FFFAAA96D620B5E439022100E40B3627F7F82F230710DC1702ACFB6126B25E12275D005371D50CCF4FDEA1A5022100C60FFCD75CDABC0F8381B16D40ADE9D24207C7FF3D58C187212F966DCF68E307022100AF794511DA483A152CF1B7396990ABDA24C9A9833490E6984F064E5613B24F15022046BC8302AF88F74D5B1C40AFD23FCA986B38B836F243F6AA3A31F2B9B92FAE95022100899AAF38D5B62870B1C23B5A13B272F813543171919C1C2EEE25AE9A38E22B36公钥:305C300D06092A864886F70D0101010500034B003048024100B06EE9C5F7923031F313AABA8E9E5F43D35CEF2CEC77C73203D7CB329451E65E467ADDC5DEA1524D7E36625A09A61E38368215615E5670EB43C925E4AE73BA830203010001公钥模数:00B06EE9C5F7923031F313AABA8E9E5F43D35CEF2CEC77C73203D7CB329451E65E467ADDC5DEA1524D7E36625A09A61E38368215615E5670EB43C925E4AE73BA83公钥指数:010001

发现公钥模数的长度是65,我们再用公钥模数和指数生成公钥,代码如下:

    public static RSAPublicKey getPublicKey(String big1,String big2) throws Exception{        BigInteger b1=new BigInteger(big1,16);        BigInteger b2=new BigInteger(big2,16);        RSAPublicKeySpec rsaPubKS=new RSAPublicKeySpec(new BigInteger(big1,16),new BigInteger(big2,16));        KeyFactory kf=KeyFactory.getInstance("RSA");        return (RSAPublicKey) kf.generatePublic(rsaPubKS);    }

这里面参数,big1是模数,big2是指数。

    static String big1="00B06EE9C5F7923031F313AABA8E9E5F43D35CEF2CEC77C73203D7CB329451E65E467ADDC5DEA1524D7E36625A09A61E38368215615E5670EB43C925E4AE73BA83";    static String big2="10001";        private static void test4() {        try {            RSAPublicKey pubkey =  CertificateUtil.getPublicKey(big1, big2);            System.out.println("公钥模数:"+CertificateUtil.bytesToHexString(pubkey.getModulus().toByteArray()));            System.out.println("公钥指数:"+CertificateUtil.bytesToHexString(pubkey.getPublicExponent().toByteArray()));            System.out.println("公钥:"+CertificateUtil.bytesToHexString(pubkey.getEncoded()));        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }

测试一下,打印结果:

公钥模数:00B06EE9C5F7923031F313AABA8E9E5F43D35CEF2CEC77C73203D7CB329451E65E467ADDC5DEA1524D7E36625A09A61E38368215615E5670EB43C925E4AE73BA83公钥指数:010001公钥:305C300D06092A864886F70D0101010500034B003048024100B06EE9C5F7923031F313AABA8E9E5F43D35CEF2CEC77C73203D7CB329451E65E467ADDC5DEA1524D7E36625A

生成的公钥一样。刚刚说,公钥模数应该是64bytes,我们去掉最前面一个byte,big1为B06EE9C5F7923031F313AABA8E9E5F43D35CEF2CEC77C73203D7CB329451E65E467ADDC5DEA1524D7E36625A09A61E38368215615E5670EB43C925E4AE73BA83时,再跑一下,打赢结果:

公钥模数:00B06EE9C5F7923031F313AABA8E9E5F43D35CEF2CEC77C73203D7CB329451E65E467ADDC5DEA1524D7E36625A09A61E38368215615E5670EB43C925E4AE73BA83公钥指数:010001公钥:305C300D06092A864886F70D0101010500034B003048024100B06EE9C5F7923031F313AABA8E9E5F43D35CEF2CEC77C73203D7CB329451E65E467ADDC5DEA1524D7E36625A09A61E38368215615E5670EB43C925E4AE73BA830203010001

一样的,也就是说生成的是64个bytes,我们回头再看看第一段,如果我们设置length把512改成588,

私钥:3082017D020100300D06092A864886F70D01010105000482016730820163020100024A0A86CD8C18CDBF06986F83DD74A372296312E026C07B3ACA4D4B77FDF297901BBB624B51F3F117F445F22F4E41C964E410A8FD05E180ECDEE86F1AD448EC4346E93D52D562B88AF3EB490203010001024A05976D7FC97D20C7641978361E4AE3CD502F2A99EB0C8A4203A4DEEC29FC9033EAE95F90FC874C3737A50916386BF31B80CBE0FDB3DF69CCC646B3ACF2161AC135051336F2A0B89539B102253DC4CD4BB2951605608762B4122E07EADAD148D4D4359DB9CF6FD6397A36951DB16FD860DF02252BA095763B3E5C94FDF95D906C51E83FADAF3FB6919D8068522DC77680E528049C6C4770D702253DB8FAAC39B76059DF2B6A2626447904E5C35BD3D07A03323966B7DA9795134CA891EAD661022527A6012F3A182ABB9D350B3B3DB612840CACC01283B3C80706E863E5E6AE5BF814D0B2FC710225107F1D24BC2A8EB55E464601CCA160E13D979807E5EB03C2AFD4D3026520E0E800197FD096公钥:3065300D06092A864886F70D01010105000354003051024A0A86CD8C18CDBF06986F83DD74A372296312E026C07B3ACA4D4B77FDF297901BBB624B51F3F117F445F22F4E41C964E410A8FD05E180ECDEE86F1AD448EC4346E93D52D562B88AF3EB490203010001公钥模数:0A86CD8C18CDBF06986F83DD74A372296312E026C07B3ACA4D4B77FDF297901BBB624B51F3F117F445F22F4E41C964E410A8FD05E180ECDEE86F1AD448EC4346E93D52D562B88AF3EB49公钥指数:010001

公钥模数是74个bytes,588/8 = 73.5,再用模数月指数生成公钥:

公钥模数:0A86CD8C18CDBF06986F83DD74A372296312E026C07B3ACA4D4B77FDF297901BBB624B51F3F117F445F22F4E41C964E410A8FD05E180ECDEE86F1AD448EC4346E93D52D562B88AF3EB49公钥指数:010001公钥:3065300D06092A864886F70D01010105000354003051024A0A86CD8C18CDBF06986F83DD74A372296312E026C07B3ACA4D4B77FDF297901BBB624B51F3F117F445F22F4E41C964E410A8FD05E180ECDEE86F1AD448EC4346E93D52D562B88AF3EB490203010001

发现一样的噢,于是,我们发现如果我们把公钥指数与公钥模数都传给对方,不管任何一个平台,我想都能用公钥加密了吧!
demo下载http://download.csdn.net/detail/gongkanaa/9810310
包含pc端加解密验证工具(很强大)!

0 0
原创粉丝点击