在模数RSA密钥中获得额外1个字节,有时也用于指数

这是我的代码片段:

int eValue = 79, t; int bitLength = 1024; // KeySize BigInteger e = new BigInteger(Integer.toString(eValue)); KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(bitLength); KeyPair kp = kpg.generateKeyPair(); KeyFactory kfactory = KeyFactory.getInstance("RSA"); RSAPublicKeySpec kspec = (RSAPublicKeySpec) kfactory.getKeySpec(kp.getPublic(), RSAPublicKeySpec.class); System.out.println("Byte Length is : " + kspec.getModulus().toByteArray().length); String testString; try { testString = new String (kspec.getModulus().toByteArray() , "ISO-8859-1"); StringBuilder tt = new StringBuilder(); for(t =0 ; t< testString.length() ; t++) { tt.append((int) testString.charAt(t)+","); } String encryptedBytes = tt.toString(); System.out.println("Mod is : " + encryptedBytes); }catch (Exception ex) { // TODO: handle exception } 

这是输出:

 Byte Length is : 129 Mod is : 0,190,193,141,230,128,124,6,201,254,135,66,162,65,147,160,76,160,181,7,141,113,8,57,193,185,206,42,125,9,169,209,124,74,233,151,10,128,180,35,24,206,213,32,48,4,39,178,60,10,249,151,50,218,220,11,124,72,64,148,135,251,133,23,54,171,25,202,157,28,21,39,239,234,48,56,79,36,127,59,203,108,189,232,216,231,237,237,90,253,19,118,29,18,142,126,254,193,189,82,15,126,139,136,45,31,133,242,187,81,62,52,5,23,11,217,171,233,7,137,115,30,93,206,236,31,196,111,153 

对于1024位长度,密钥模数应该是128字节,对于2048,它应该是256,但是我得到额外的一个字节(总是在第一个字节添加0),需要帮助重新开始这个…

谢谢,Pawan

启动时00h值字节的原因是因为BigInteger.toByteArray()返回带符号的表示。 只要以比特为单位的密钥长度为N * 8(或密钥长度%8 = 0),则RSA模数的带符号表示将始终以开始时的00h值字节为特征。

如果初始字节为零,只需将其复制到密钥长度的数组(以字节为单位)即可删除。 请注意,如果您有一个私有指数,它也可能于以字节为单位的密钥长度,因此将其复制到新字节数组的末尾。 通常,这种方法称为I2OS或I2O(整数到八位字符串),其中八位字节sting(java中的字节数组)具有指定的长度。

 /** * Encodes the given value as a unsigned Big Endian within an octet string * of octetStringSize bytes. * * @param i * the integer to encode * @param octetStringSize * the number of octets in the octetString returned * @return the encoding of i * @throws IllegalArgumentException * if the given integer i is negative * @throws IllegalArgumentException * if the octetStringSize is zero or lower * @throws IllegalArgumentException * if the given BigInteger does not fit into octetStringSize * bytes */ public static byte[] integerToOctetString(final BigInteger i, final int octetStringSize) { // throws NullPointerException if i = null if (i.signum() < 0) { throw new IllegalArgumentException( "argument i should not be negative"); } if (octetStringSize <= 0) { throw new IllegalArgumentException("octetStringSize argument (" + octetStringSize + ") should be higher than 0 to store any integer"); } if (i.bitLength() > octetStringSize * Byte.SIZE) { throw new IllegalArgumentException("argument i (" + i + ") does not fit into " + octetStringSize + " octets"); } final byte[] signedEncoding = i.toByteArray(); final int signedEncodingLength = signedEncoding.length; if (signedEncodingLength == octetStringSize) { return signedEncoding; } final byte[] unsignedEncoding = new byte[octetStringSize]; if (signedEncoding[0] == (byte) 0x00) { // skip first padding byte to create a (possitive) unsigned encoding for this number System.arraycopy(signedEncoding, 1, unsignedEncoding, octetStringSize - signedEncodingLength + 1, signedEncodingLength - 1); } else { System.arraycopy(signedEncoding, 0, unsignedEncoding, octetStringSize - signedEncodingLength, signedEncodingLength); } return unsignedEncoding; } /** * Returns a BigInteger that is the value represented by the unsigned, Big * Endian encoding within the given octetString. * * @param octetString * the octetString containing (only) the encoding * @return the value represented by the octetString */ public static BigInteger octetStringToInteger(final byte[] octetString) { // arguments are signum, magnitude as unsigned, Big Endian encoding return new BigInteger(1, octetString); } /** * Returns the minimum number of bytes required to directly store the given * number of bits. * * @param bitSize * the bitSize * @return the size as a number of bytes * @throws IllegalArgumentException * if the given bitSize argument is negative */ public static int bitSizeToByteSize(final int bitSize) { if (bitSize < 0) { throw new IllegalArgumentException("bitSize (" + bitSize + " should not be negative"); } return (bitSize + Byte.SIZE - 1) / Byte.SIZE; } 

您可以使用Arrays.deepToString()直接打印字节数组:

 String encryptedBytes = Arrays.deepToString(new Object[] { kspec.getModulus().toByteArray() }) 

我怀疑你有签名号码和无签名号码有问题。 128位模数是无符号的,但是将它存储在BigInteger中有时可能需要129位,因此需要额外的字节。

正如Maarten Bodewes所回答的那样,额外的字节是BigInteger标志的空间。

如果预期的大小是已知的并且Hex是可接受的,我会使用这样的东西:

 System.out.printf("Mod is : %0256x%n" , kspec.getModulus());