当前位置: 首页 > 后端技术 > Java

在JAVA中使用P和Q分量来计算N和D进行RSA运算

时间:2023-04-01 20:45:14 Java

最近在Java中需要使用PQ形式的私钥来进行RSA加解密运算。原以为Java中应该有很多类似的例子,结果都找到了。是来自ND形式的私钥,没有人使用组件P和Q来计算N和D进行运算。我对Java中的RSA操作不是很熟悉,所以只能一点一点的做。身边的Java小仙女们身边好像没有中国余数定理,不会遇到P和Q吧?别管他们,开始工作吧。1.BigInteger类Java中有现成的BigInteger类用于大数运算,可以直接使用该类进行运算,总结一下使用中遇到的坑。Java大部分都是多1位来表示符号的,所以如果1024byte的N在BigInteger中是1025bit,最高位比符号位多1位,所以如果在BigInteger中使用toByteArray(),就可以得到二的大数的补码,如果需要导出BigInteger中的数据,需要忽略符号位,从第二个字节开始复制。如果从第一个字节开始复制,最后一个字节将丢失,符号位将被保存。BigInteger类提供了modInverse方法,可以直接求$d=e^{-1}=mod\\phi(n)$,省去很多麻烦。2、Cipher类javax.crypto.Cipher类有一个getInstance()方法,参数是“算法/模式/填充方法”,因为我只有一段定长128字节的数据用于RSA计算,和自己fill和defill,按照sun的文档中的描述,填写“RSA/None/NoPadding”,但是编译的时候报错,提示不支持。我在网上搜索了一下,发现默认的CryptProvider是不支持NoPadding的。它必须是PKCS#1的填充。这是非常不可靠的。后来发现Jdk1.7或者哪个版本之后不支持None模式,ECB模式就可以了。我没有验证之前的版本是否支持None。3、代码RSACrtUtil.javapackagecom.zhantianzuo.alg;importjava.math.BigInteger;importjava.security.Key;importjava.security.KeyFactory;importjava.security.KeyPair;importjava.security.KeyPairGenerator;importjava.security.NoSuchAlgorithmException;导入java.security.Security;导入java.security.interfaces.RSAPrivateCrtKey;导入java.security.interfaces.RSAPublicKey;导入java.security.spec.RSAPrivateKeySpec;导入java.security.spec.RSAPublicKeySpec;导入javax。crypto.Cipher;/****RSACrtUtilRSA加解密*使用中国余数定理式密钥*私钥为P和Q,公钥为N,E固定为0x10001**@Date2016.9.6**@versionv1.0**@authorZhaoYangcnrgc@163.com*/publicclassRSACrtUtil{publicstaticfinalintRSA_MODULUS_LEN=128;publicstaticfinalintRSA_P_LEN=RSA_MODULUS_LEN/2;publicstaticfinalintRSA_Q_LEN=RSA_MODULUSp_LEN/2statintpublicExponent=65537;publicstaticfinalStringKEY_ALGORITHM_MODE_PADDING="RSA/ECB/NoPadding";//不填publicstaticfinalStringKEY_ALGORITHM="RSA";//不填/***prikey_crt_decrypt使用PQ的RSA私钥解密*私钥格式前半部分为P,后半部分为Q***/publicstaticbyte[]prikey_crt_decrypt(byte[]data,byte[]prikey)throwsException{byte[]buf_p=newbyte[RSA_P_LEN];byte[]buf_q=新字节[RSA_Q_LEN];//buf_p[0]=(字节)0x00;//buf_q[0]=(byte)0x00;System.arraycopy(prikey,0,buf_p,0,RSA_P_LEN);System.arraycopy(prikey,RSA_P_LEN,buf_q,0,RSA_Q_LEN);///***1.p,q计算n**/BigIntegerp=newBigInteger(1,buf_p);BigIntegerq=newBigInteger(1,buf_q);BigIntegern=p.multiply(q);//n=p*q/***2.计算d=(p-1)*(q-1)mode**/BigIntegerp1=p.subtract(BigInteger.valueOf(1));BigIntegerq1=q.subtract(BigInteger.valueOf(1));大整数h=p1。相乘(q1);//h=(p-1)*(q-1)BigIntegere=BigInteger.valueOf(publicExponent);//大整数d=h.mod(e);BigIntegerd=e.modInverse(h);/***3.创建RSA私钥**/RSAPrivateKeySpeckeyspec=newRSAPrivateKeySpec(n,d);KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);密钥privateKey=keyFactory.generatePrivate(keyspec);/***4.数据解密**/Ciphercipher=Cipher.getInstance(KEY_ALGORITHM_MODE_PADDING);cipher.init(Cipher.DECRYPT_MODE,privateKey);/***5.返回结果**/returncipher.doFinal(data);}/***pubkey_encrypt公钥加密*密钥为N**/publicstaticbyte[]pubkey_encrypt(byte[]data,byte[]pubkey)throwsException{/***1.初始化大数取模n和公钥指数e**/byte[]pubkey_buf=newbyte[RSA_MODULUS_LEN+1];//多一个字节符号位pubkey_buf[0]=(byte)0x00;System.arraycopy(pubkey,0,pubkey_buf,1,RSA_MODULUS_LEN);//BigIntegere=BigInteger.valueOf(publicExponent);BigIntegern=newBigInteger(pubkey_buf);/***2.创建RSA公钥**///RSAPublicKeySpeckeyspec=newRSAPublicKeySpec(n,e);KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);密钥publicKey=keyFactory.generatePublic(keyspec);/***3.数据加密**/Ciphercipher=Cipher.getInstance(KEY_ALGORITHM_MODE_PADDING);cipher.init(Cipher.ENCRYPT_MODE,publicKey);/***5.返回结果**/returncipher.doFinal(data);}publicstaticvoidgenerateKeyPair(byte[]pubkey,byte[]prikey)throwsException{KeyPairGeneratorkeyPairGenerator=KeyPairGenerator.getInstance(KEY_ALGORITHM);keyPairGenerator.initialize(RSA_MODULUS_LEN*8);密钥对yPair=keyPairGenerator.generateKeyPair();RSAPublicKeypublicKey=(RSAPublicKey)keyPair.getPublic();RSAPrivateCrtKeyprivateKey=(RSAPrivateCrtKey)keyPair.getPrivate();//BigIntegern=publicKey.getModulus();BigIntegerp=privateKey.getPrimeP();BigIntegerq=privateKey.getPrimeQ();/***BigInteger中有一个符号位,所以直接使用toByteArray会包含符号位,*c的代码中没有符号位,所以1024bitn,在java中BigInteger是1025bitlong*直接复制128byte,正数的第一个字节为0,最后一个字节稍后丢失**/System.arraycopy(n.toByteArray(),1,pubkey,0,128);System.arraycopy(p.toByteArray(),1,prikey,0,64);System.arraycopy(q.toByteArray(),1,prikey,64,64);//}}Test.javapackagecom.zhantianzuo.alg;importjava.math.BigInteger;importjava.security.Key;importjava.security.KeyPair;importjava.security.KeyPairGenerator;importjava.security.NoSuchAlgorithmException;importjava.security.interfaces.RSAPrivateCrtKey;导入java.security.interfaces.RSAPublicKey;公共类测试{privatestaticfinalStringALGORITHM="RSA";privatestaticfinalintkey_len=128;publicstaticvoidmain(String[]args){//byte[]pubkey=newbyte[128];byte[]prikey=newbyte[128];尝试{RSACrtUtil.generateKeyPair(pubkey,prikey);}catch(Exceptione){//TODO自动生成的catch块e.printStackTrace();}//整数i;byte[]明文=空;byte[]密文=空;byte[]data=newbyte[key_len];for(i=0;i

最新推荐
猜你喜欢