5 votes

Obtenir 1 octet supplémentaire dans le module de la clé RSA et parfois aussi pour les exposants.

Voici mon extrait de code :

 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
 }

Et voici le résultat :

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

Pour une clé de 1024 bits, le module devrait être de 128 octets et pour 2048 il devrait être de 256, mais j'obtiens un octet supplémentaire (ajoutant toujours 0 au tout premier octet), j'ai besoin d'aide pour résoudre ce

Merci, Pawan

13voto

owlstead Points 22329

La raison de l'octet de valeur 00h au début est que BigInteger.toByteArray() renvoie la représentation signée. Tant que la longueur de la clé en bits est N*8 (ou longueur de la clé % 8 = 0), la représentation signée d'un module RSA comportera toujours un octet de valeur 00h au début.

Il suffit de supprimer l'octet initial s'il est nul en le copiant dans un tableau de la longueur de la clé en octets. Notez que si vous avez un exposant privé, il peut également être plus court que la longueur de la clé en octets, donc copiez-la à la fin du nouveau tableau d'octets. Normalement, ce type de méthode est connu sous le nom de I2OS ou I2O (integer to octet string), où la chaîne d'octets (byte array en java) a une longueur spécifiée.

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

3voto

artbristol Points 17755

Vous pouvez utiliser Arrays.deepToString() pour imprimer directement un tableau d'octets :

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

Je pense que vous avez des problèmes avec les nombres signés et non signés. Le modulus de 128 bits n'est pas signé, mais son stockage dans un BigInteger peut parfois nécessiter 129 bits, d'où l'octet supplémentaire.

0voto

Usagi Miyamoto Points 4622

Comme Maarten Bodewes a répondu, l'octet supplémentaire est de l'espace pour le BigInteger Le signe de l'entreprise.

Si la taille attendue est connue et que l'Hex est acceptable, j'utiliserais quelque chose comme ceci :

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

0voto

Kapali Points 21

La meilleure réponse à cette question se trouve dans le lien Stackoverflow suivant. La solution est également très simple et s'applique à toutes les applications de cryptographie, car la longueur de toutes les clés cryptographiques est un multiple exact de 8.

BigInteger vers byte[]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X