Конечно, есть несколько способов сделать это.Но давайте предположим, что нам нужны положительные значения (обычно требующиеся для криптографии), и что мы хотим, чтобы результат работал для ECB и CBC, а также, например, для шифрования в режиме CTR.В этом случае нам также нужно убедиться, что начальные нули обрабатываются изящно, потому что начальные нули имеют значение в зашифрованном тексте, но не для чисел.
И, так как это язык, работающий на JVM, мы будемиспользуйте также старший порядковый номер.
Отрицательных значений и нулевых байтов можно легко избежать, добавив битовые / байтовые значения в левую часть.Например, мы могли бы использовать общеизвестные значения, которые позволили бы вам иметь некоторую минимальную защиту от искажения числа зашифрованного текста.Тогда вы получите в Java:
private static BigInteger ciphertextToNumber(byte[] ct) {
ByteBuffer fixed = ByteBuffer.allocate(2 + ct.length);
fixed.put((byte) 0x4D).put((byte) 0x42);
fixed.put(ct);
BigInteger number = new BigInteger(fixed.array());
return number;
}
private static byte[] numberToCiphertext(BigInteger ctAsNumber) {
// if the number is negative then the buffer will be too small
if (ctAsNumber.signum() < 0 || ctAsNumber.bitLength() < 15) {
throw new IllegalArgumentException("Magic of ciphertext number doesn't match");
}
ByteBuffer fixed = ByteBuffer.allocate((ctAsNumber.bitLength() + Byte.SIZE - 1) / Byte.SIZE);
fixed.put(ctAsNumber.toByteArray());
fixed.flip();
if (fixed.get() != (byte) 0x4D || fixed.get() != (byte) 0x42) {
throw new IllegalArgumentException("Magic of ciphertext number doesn't match");
}
byte[] ct = new byte[fixed.remaining()];
fixed.get(ct);
return ct;
}
Это относительно эффективно и не увеличивает слишком большое возможное число по сравнению с зашифрованным текстом (так как зашифрованный текст может иметь любое значение байта, это, конечно,не возможно сжать это вместо этого).Одной из оптимизаций было бы извлечение байтовых значений магии непосредственно из BigInteger
, но одна дополнительная копия зашифрованного текста, вероятно, не сильно повредит для такого рода целей.
Я оставлю это напреобразовать в Scala.
Другая идея состоит в том, чтобы использовать I2OSP или OS2IP, как определено в RFC RSA, но учтите, что заполнение RSA уже выполняет тот же вид заполнения слева, чтобы убедиться, что байтпреобразование массива в целое число обрабатывается изящно.Кроме того, зашифрованный текст RSA всегда имеет тот же размер, что и модуль, а шифрование AES может возвращать разные размеры.