java密码学中如何将位插入块中? [英] How insert bits into block in java cryptography?

查看:13
本文介绍了java密码学中如何将位插入块中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个涉及密码学的简单 Java 程序.

I am trying to make a simple Java program that involves cryptography.

首先,我从文件 clearmsg.txt 中读取了一个 32 字节的块.然后我将此块转换为整数,并将其用于加密.不幸的是,密文的大小不是静态的;有时它返回 30 个字节,有时返回 26 个字节.这似乎与添加操作的结果无关.

First I read a block of 32 bytes from file clearmsg.txt. Then I convert this block to integer number, and use it for encryption. Unfortunately the size of the ciphertext is not static; sometimes it returns 30 bytes and sometimes 26 bytes. This seems independent on result of add operation.

我怎样才能确保它变成一个 32 字节的密码块?如何向该块添加位/字节?因为当我尝试解密这个块时,我需要读取 32 个密文字节.

How can I make sure it becomes a cipher block of 32 bytes? How add bits / bytes to this block? Because when I try decrypt this block I need to read 32 ciphertext bytes.

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();
    }
}

推荐答案

对于加密,需要一个函数,通常称为 Integer to Octet String Primitive 或 I2OSP.对于解密,您需要一个 OS2IP 函数来转换回整数.在我在密码学姊妹网站上的回答中对两者进行了解释.它们是 RSA PKCS#1 规范的一部分,为此指定了 2.2 版此处.

For the encrypt a function is required that is normally called Integer to Octet String Primitive or I2OSP. For decryption you need an OS2IP function to convert back to integers. Both are explained in my answer on the cryptography sister site. They are part of the RSA PKCS#1 specifications, for which version 2.2 is specified here.

I2OSP 和 OS2IP 函数也用于其他加密原语.例如,它们可用于椭圆曲线密码术以创建平面 ECDSA 签名或 EC 公钥表示.

The I2OSP and OS2IP functions are also used for other cryptographic primitives. For instance, they can be used for Elliptic Curve Cryptography to create flat ECDSA signatures or EC public key representations.

这些函数用于编码/解码为给定大小的八位字节字符串(字节数组).此大小通常与 RSA 加密的模数(在您的情况下为 P)的大小直接相关.

These functions are used to encode/decode to an octet string (byte array) of a given size. This size is normally directly related to the size of the modulus (P in your case) of RSA encryption.

I2OSP 函数应该这样编码:

The I2OSP function should be coded like this:

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 中):

Of course, to use this with the correct size in octets / bytes you should first know the key size in bytes first. For an RSA public- or private key this can be easily calculated from the modulus (in case it is not directly available, as in the Java JCA):

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

请注意,RSAPublicKeyRSAPrivateKeyRSAPrivateCrtKey 都扩展了 RSAKey,后者提供了对模数的访问.因此,您可以直接使用这些类的实例作为此方法的参数.当然,Java中的RSA提供程序在CipherSignature实现类中已经包含了I2OSP和OS2IP,但是从位大小到字节大小的转换(没有浮点计算)可以派上用场.

Note that RSAPublicKey, RSAPrivateKey and RSAPrivateCrtKey all extend RSAKey which provides access to the modulus. So you can use instances of these classes directly as argument for this method. Of course, the RSA providers in Java already contain I2OSP and OS2IP within the Cipher and Signature implementation classes, but the conversion from bit size to byte size (without floating point calculations) could come in handy.

幸运的是,反向函数没有那么复杂:

Fortunately, the reverse function is not as complicated:

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); 
}

我保留了大小验证,因此可以使用预期的八位字节大小调用它,即使计算本身不需要它.

I've kept in the size validation so it can be called with the expected octet size, even though it is not required for the calculation itself.

这篇关于java密码学中如何将位插入块中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆