3

暗号化を含む単純な Java プログラムを作成しようとしています。

まず、ファイル clearmsg.txt から 32 バイトのブロックを読み取ります。次に、このブロックを整数に変換し、暗号化に使用します。残念ながら、暗号文のサイズは静的ではありません。30 バイトを返すこともあれば、26 バイトを返すこともあります。これは、追加操作の結果とは無関係のようです。

32 バイトの暗号ブロックになるようにするにはどうすればよいですか? このブロックにビット/バイトを追加するにはどうすればよいですか? このブロックを復号化しようとすると、32 暗号文バイトを読み取る必要があるためです。

private void ENC_add() {

    final File clearmsg = new File("F:/java_projects/clearmsg.txt");
    final File ciphermsg = new File("F:/java_projects/ciphermsg.txt");
    final byte[] block = new byte[32];
    try {
        final FileInputStream fis = new FileInputStream(clearmsg);
        final FileOutputStream fcs = new FileOutputStream(ciphermsg);
        int i;
        while ((i = fis.read(block)) != -1) {
            // Is this process true
            // here M2 (Plain text) shuld be 32 byte
            M2 = new BigInteger(block);
            // here encrypt M2 by add k1 where k1 any number less than P
            CM2 = M2.add(K1).mod(P);
            // here my problem some time Cipher CM2 length 31 , some time CM2 length 32 ,some time CM2 length 30
            System.out.println("THE CM2=" + CM2.toByteArray().Length);
            fcs.write(CM2.toByteArray(), 0, i);
        }
        fcs.close();

    }

    catch (final IOException e) {
        e.printStackTrace();
    }
}

// Here problem for decrypt
private void DEC_ADD() {

    // DECREPT METHOD
    final File ciphermsg = new File("F:/java_projects/ciphermsg.txt");
    final File clearmsg = new File("F:/java_projects/rciphermsg.txt");
    final byte[] block = new byte[32];
    try {
        final FileInputStream fis = new FileInputStream(ciphermsg);
        final FileOutputStream fos = new FileOutputStream(clearmsg);
        int i;
        while ((i = fis.read(block)) != -1) {
            // CM2 NOT STATIC BITS NUMBER BECAUSE INDEPENDET ON RESULT ADDITIONAL AND PRIME NUMBER P through ENCRYPT
            // Process
            CM2 = new BigInteger(block);
            // here RM2 is decrypt cipher (CM2) NOTE When encrypt above M2 WAS 32 bytes and Cipher CM2 was 30 bytes
            // and When I read from file 32 bytes then this is my problem
            RM2 = CM2.subtract(K1).mod(P);

            fos.write(RM2.toByteArray(), 0, i);
        }
        fos.close();
        System.out.println("THE RM2=" + CM2.bitLength());
    } catch (final IOException e) {
        e.printStackTrace();
    }
}
4

1 に答える 1

4

暗号化には、通常 Integer to Octet String Primitive または I2OSP と呼ばれる関数が必要です。復号化するには、整数に戻すための OS2IP 関数が必要です。どちらも、暗号化の姉妹サイトでの私の回答で説明されています。これらは RSA PKCS#1 仕様の一部であり、バージョン 2.2 がここで指定されています。

I2OSP および OS2IP 関数は、他の暗号プリミティブにも使用されます。たとえば、楕円曲線暗号に使用して、フラットな ECDSA 署名または EC 公開鍵表現を作成できます。

これらの関数は、指定されたサイズのオクテット文字列 (バイト配列) にエンコード/デコードするために使用されます。このサイズは通常、RSA 暗号化のモジュラス (この場合は P) のサイズに直接関係しています。

I2OSP 関数は次のようにコーディングする必要があります。

public static byte[] i2osp(final BigInteger i, final int size) {
    if (size < 1) {
        throw new IllegalArgumentException("Size of the octet string should be at least 1 but is " + size);
    }

    if (i == null || i.signum() == -1 || i.bitLength() > size * Byte.SIZE) {
        throw new IllegalArgumentException("Integer should be a positive number or 0, no larger than the given size");
    }

    final byte[] signed = i.toByteArray();
    if (signed.length == size) {
        // (we are lucky, already the right size)
        return signed;
    }

    final byte[] os = new byte[size];
    if (signed.length < size) {
        // (the dynamically sized array is too small, pad with 00 valued bytes at the left)
        System.arraycopy(signed, 0, os, size - signed.length, signed.length);
        return os;
    }

    // (signed representation too large, remove leading 00 valued byte)
    System.arraycopy(signed, 1, os, 0, size);
    return os;
}

もちろん、これを正しいサイズのオクテット/バイトで使用するには、最初に鍵のサイズをバイト単位で知る必要があります。RSA 公開鍵または秘密鍵の場合、これはモジュラスから簡単に計算できます (Java JCA のように直接利用できない場合)。

public static int keySizeInOctets(RSAKey key) {
    int keySizeBits = key.getModulus().bitLength();
    int keySizeBytes = (keySizeBits + Byte.SIZE - 1) / Byte.SIZE;
    return keySizeBytes;
}

RSAPublicKeyRSAPrivateKeyおよびモジュラスへのアクセスを提供するRSAPrivateCrtKeyすべての拡張に注意してください。RSAKeyしたがって、これらのクラスのインスタンスをこのメソッドの引数として直接使用できます。もちろん、Java の RSA プロバイダーにはCipherSignature実装クラス内に I2OSP と OS2IP が既に含まれていますが、ビット サイズからバイト サイズへの変換 (浮動小数点計算なし) が役立つ場合があります。


幸いなことに、reverse 関数はそれほど複雑ではありません。

public static BigInteger os2ip(final byte[] data, final int size) {
    if (data.length != size) {
        throw new IllegalArgumentException("Size of the octet string should be precisely " + size);
    }

    return new BigInteger(1, data); 
}

計算自体には必要ありませんが、予想されるオクテット サイズで呼び出すことができるように、サイズの検証を続けました。

于 2013-09-16T09:33:12.693 に答える