Getting 1 byte extra in the modulus RSA Key and sometimes for exponents also

Related searches

Here is my code snippet:

 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
 }

And here is the output:

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

For 1024 bit lenght key modulus should be 128 bytes and for 2048 it should be 256, but I am getting one byte extra (Adding 0 always at the very first byte), Need Help to reslove this..

Thanks, Pawan

The reason for the 00h valued byte at the start is because BigInteger.toByteArray() returns the signed representation. As long as the key length in bits is N*8 (or key length % 8 = 0) then the signed representation of an RSA modulus will always feature a 00h valued byte at the start.

Simply remove the initial byte if it is zero by copying it into an array of the key length in bytes. Note that if you have a private exponent, it might also be shorter than the key length in bytes, so copy it to the end of the new byte array. Normally, this kind of method is known as I2OS or I2O (integer to octet string), where the octet sting (byte array in java) has a specified length.

/**
 * 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;
}

Is RSA key size the size of private key exponent?, Getting 1 byte extra in the modulus RSA Key and sometimes for exponents also. 发表于 2019-6-14 | | 暂无分类. Here is my code snippet: int eValue = 79, t;� Find answers to RSA - Getting one extra byte in the modulus the-modulus-rsa-key-and-sometimes-for-exponents also be shorter than the key length in bytes, so

You can use Arrays.deepToString() to print a byte array directly:

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

I suspect you are having trouble with signed vs. unsigned numbers. The 128-bit modulus is unsigned, but to store it in a BigInteger might sometimes take 129 bits, hence the extra byte.

RSA, exponents that are two or even three bytes less than the size of the modulus No, the RSA key size is not the size of the private key exponent. Sometime, a private exponent is computed as d=e−1modφ(N), where φ() is do is precisely equivalent to the smaller d, and hence the extra work buys you absolutely nothing. It is possible to get both the local and peer public RSA key modulus and exponent using wolfSSL. This can be done in the following manner: 1) Getting the peer's public RSA key modulus and exponent. a) Use wolfSSL_get_peer_certificate() to get a pointer to the peer's CYASSL_X509 object.

As Maarten Bodewes has answered, the extra byte is space for the BigInteger's sign.

If the expected size is known and Hex is acceptable, i would use something like this:

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

RSA Algorithm, The RSA algorithm can be used for both public key encryption and digital RSA can also be used to sign a message, so A can sign a message using Compute the secret exponent d, 1<d<ϕ, such that ed≡1modϕ. The other convention, sometimes used, is that the key length is the number of bytes needed to store n� The modulus So the key has type RSA, and its modulus has length 257 bytes, except that the first byte has value "00", so the real length is 256 bytes (that first byte was added so that the value is considered positive, because the internal encoding rules call for signed integers, the first bit defining the sign). 256 bytes is 2048 bits.

This question is best answered in the following Stackoverflow link. The solution is also very simple and applies to all cryptography applications because the length of all crypto keys are exact multiples of 8.

BigInteger to byte[]

[PDF] Implementation of Cryptographic Schemes 1, against RSA and other Exponentiation-Based Public-Key Algo- rithms . 1.2.1 gi ← gi−1 � g mod n. 2. A ← gEt. 3. FOR i FROM t − 1 DOWN TO 0 DO: This way, we trade one multiplication for three extra additions (subtractions can be The field of cryptographic implementation, sometimes also referred to as crypto engi-. The resulting byte array has a 0 byte at the start. When the Go version decodes the modulus into a Big Int to feed it to an RSA PublicKey structure everything works. The .NET RSAPKCS1SignatureDeformatter doesn't seem to work with a key from that same byte array. The following hack to JsonWebKeySet.cs to get rid of that first byte makes

During the research I came across a recomendation from vendor's documentation: please, check if the very first byte of the Modulus (N) of the private key is greater than 0x80. If not, please, generate another key and do the same check. Well, if you think about it, if it is less than 0x80 the key won't actually have 2048 bits but less than that.

Size of the RSA modulus in bits. size_in_bytes ¶ The minimal amount of bytes that can hold the RSA modulus. Crypto.PublicKey.RSA.oid = '1.2.840.113549.1.1.1'¶ Object ID for the RSA encryption algorithm. This OID often indicates a generic RSA key, even when such key will be actually used for digital signatures.

It can be shown that the order of all elements in the group mod n divide phi(n) = (p - 1)*(q - 1) (this is how RSA works, by finding the inverse of e mod phi(n)). It can also be shown that, as long as phi(n) has no small factors (which is normally the case for RSA numbers) almost all elements have order of either phi(n)/2 or phi(n)/4.

Comments
  • I suspect the conversion from ByteArray to string, try another conversion : stackoverflow.com/questions/332079/…
  • PS haven't unit tested the given methods yet, but should be ok according to "good" scenarios
  • Hmm, I always use a toHex helper method myself, which uses a StringBuilder of the byte array length times two, and then sb.append(String.format("%02X")) for each byte. Hexadecimals are more usefull I think.
  • you're right about hex being better. There's always commons-codec's Hex.encodeHexString of course.
  • it prints only upto 127, for greater than 128 it prints -ve number, also 0 is there if first byte is 128 or greater.
  • perform <byte value> & 0xFF to get a positive integer with the right value, e.g. String.format("%02X", data[i] & 0xFF)... sorry for that.