Which encryption scheme satisfies the requirements of decimal plaintext and ciphertext and retains length?

I need an encryption scheme where plaintext and encrypted text are composed entirely of decimal digits.

In addition, plaintext and ciphertext should be the same length.

Also, the basic encryption algorithm should be an industry standard. I don’t mind if its symmetric (like AES) or asymmetric (like RSA), but it should be a recognized algorithm for which I can get a FIPS-140 approved library. (Otherwise, it will not pass the security check stage).

Using AES OFB is great for saving the input length based on hexadecimal (that is, where each byte has 256 possible values: 0x00 → 0xFF). However, this will not work for my means, since plaintext and ciphertext should be completely decimal.

NB: "Integer decimal numbers" can be interpreted in two ways - both of which are acceptable for my requirements:

  • The input and output bytes are the characters '0' → '9' (i.e. byte values: 0x30 → 0x39)
  • Input and output bytes have 100 (decimal) values: 0x00 → 0x99 (i.e. BCD)

Additional Information: The maximum length of the plaintext and the length of the ciphertext is likely to be 10 decimal digits. (For example, 10 bytes when using "0" → "9" or 5 bytes when using BCD)

Consider the following example to understand why AES fails: The input string is an 8-digit number. The maximum 8-digit number: 99999999 in hexadecimal is: 0x5f5e0ff

This can be thought of as 4 bytes: <0x05> <0xf5> <0xe0> <0xff>

If I use AES OFB, I get 4 byte output.

The maximum possible 4-byte output of ciphertext is <0xFF> <0xFF> <0xFF> <0xFF>

Converting this value to an integer gives: 4294967295 That is, a 10-digit number.

==> Two digits are too long.

Last: There are no restrictions on the length of any keys / IV.

+6
c ++ cryptography encryption aes
source share
9 answers

Use AES / OFB or any other stream cipher. It will generate a pseudo-random bit stream. Typically, you should XOR these plaintext bits. Instead of this:

For every decimal digit in the plaintext Repeat Take 4 bits from the keystream Until the bits form a number less than 10 Add this number to the plaintext digit, modulo 10 

To decrypt, do the same, but subtract instead in the last step.

I believe this should be as secure as a regular stream cipher. If the sequence of numbers 0-15 is indistinguishable from random, then the subsequence of only those numbers that are less than 10 should still be random. Using add / subtract instead of XOR should still produce arbitrary output if one of the inputs is random.

+7
source share

I'm not an encryption guru, but the obvious question is: can I use One Time Pad encryption? Then you can simply incorporate a large block of truly random bits into your decoding system and use random data to convert decimal digits in a reversible way.

If this is acceptable, we just need to figure out how the decoder knows where in the random block to look for a key to decode any particular message. If you can send a plaintext timestamp using encrypted text, then it’s easy: convert the timestamp to a number, say, the number of seconds from the date of an era, a module that is listed by the length of the random block, and you have an offset within the block.

With a sufficiently large block of randomness, this should be irreparable. You could encrypt random bits with strong encryption, so the user must enter a long password to unlock the decoder; thus, even if decryption software were hijacked, it would still not be easy to crash the system.

If you have an interest in this, and I would like for me to expand further, let me know. I do not want to spend a lot of time on an answer that does not meet your needs.

EDIT: Good, with a tiny bit of support (“you can be on something”). I am expanding my answer.

The idea is that you get a block of randomness. One easy way to do this is to simply extract data from Linux /dev/random . Now I'm going to assume that we have a way to find the index in this randomness block for each message.

Index into a random block and pull out ten bytes of data. Each byte is a number from 0 to 255. Add each of these numbers to the corresponding digit from the plaintext, modulo 10, and you have the numbers of the ciphertext. You can easily reverse this if you have a random data block and an index: you get random bits and subtract them from the encryption digits modulo 10.

You can think of it as placing numbers from 0 to 9 in a ring. Adding is counting clockwise around the ring, and subtracting is counterclockwise. You can add or subtract any number, and it will work. (My original version of this answer suggested using only 3 bits per digit. Not enough, as @Baffe Boyois below. Thanks for this correction.)

If a simple text digit is 6 and a random number is 117, then: 6 + 117 == 123, modulo 10 == 3. 3 - 117 == -114, modulo 10 == 6.

As I said, the problem of finding the index is simple if you can use external plaintext information such as a timestamp. Even if your opponent knows that you are using a timestamp to help decode messages, it does nothing good without a random block.

The index search problem is also simple if the message is always delivered; you can have a consistent index generation system and say, "This is the fourth message I received, so I use the fourth index in the series." As a trivial example, if this is the fourth message received, you can agree to use the index value 16 (4 for the fourth message, 4 bytes per one-time notepad). But you can also use numbers from an approved pseudo-random number generator, initialized with a consistent constant value as a seed, and then you get a somewhat unpredictable series of indices in a random block.

Depending on your needs, you may have a really large chunk of random data (hundreds of megabytes or even more). If you use 10 bytes as a one-time pad and never use overlapping pads or re-pads, then 1 megabyte of random data will produce more than 100,000 one-time pads.

+1
source share

One potential candidate is the FFX mode, which was recently sent to NIST.

+1
source share

In stream ciphers, nonce is required for security; the same key stream state should never be reused for different messages. This nonce adds to the effective length of the ciphertext.

The block cipher used in streaming mode has essentially the same problem: a unique unique initialization vector must be included in the encryption text.

Many stream ciphers are also vulnerable to ciphertext processing, where inverting bits in ciphertext unevenly flips the corresponding bit in plaintext.

If numbers are randomly selected and each number is encrypted only once and the numbers are shorter than the block size, ECB offers good protection. In these circumstances, I would recommend AES in ECB mode as a solution that minimizes the length of the encrypted text, while providing reliable protection of confidentiality and integrity.

If there is some other information in the context of ciphertext that can be used as an initialization vector (or nonce), then this might work. It can be something explicit, like a transaction identifier at the time of purchase, or something implicit, like a message sequence number (which can be used as a counter in CTR mode). I believe VeriShield is doing something like this.

+1
source share

You can use the octal format, which uses the numbers 0-7, and three digits make up the byte. This is not the most effective solution, but it is quick and easy.

Example:

 Text: Hello world! Hexadecimal: 48 65 6C 6C 6F 20 77 6F 72 6C 64 21 Octal: 110 145 154 154 157 040 167 157 162 154 144 041 

(spaces added for clarity to separate bytes)

0
source share

I do not believe that your requirement can be fulfilled (generally easy), although you can close it pretty close.

AES (like most encryption algorithms) is written to work with octets (i.e. 8-bit bytes), and it is going to create 8-bit bytes. Once this is done, converting the result to using only decimal digits or BCD values ​​will be impossible. Therefore, your only choice is to convert the input from decimal or binary digits to what fills the octet as fully as possible. You can then encrypt this and finally re-encode the output to use only decimal or binary digits.

When you convert ASCII digits to fill in octets, it compresses the input a bit. Then the encryption will produce the same output size as the input. Then you encode this to use only decimal digits, which will expand to roughly the original size.

The problem is that neither 10 nor 100 is a number that you easily type exactly in bytes. Numbers from 1 to 100 can be encoded in 7 bits. So you basically see them as a bit stream, putting them 7 bits at a time, but picking them 8 bits at a time to get bytes for encryption.

This uses the space somewhat better, but it is still not perfect. 7 bits can encode values ​​from 0 to 127, and not just from 0 to 99, therefore, although you will use all 8 bits, you will not use every possible combination of these 8 bits. Similarly, as a result, one byte will turn into three decimal digits (from 0 to 255), which will obviously lose some space. As a result, your result will be slightly larger than your input.

To get closer to this, you can compress your input with something like Huffman or LZ * compression (or both) before encrypting it. Then you will do roughly the same thing: encrypt the bytes and encode the bytes using values ​​from 0 to 9 or from 0 to 99. This will allow you to better use the bits in the bytes that you encrypt, so you will spend very little space in this conversion, but does nothing to improve coding on the output side.

0
source share

For those who doubt the FFX AES mode, please contact me for more information. Our implementation is AES mode, which effectively sits on top of existing ciphers. the proof / validation specification is on the NIST Modes website. FFSEM AES mode is enabled in FFX mode.

http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/ffx/ffx-spec.pdf

If that makes sense, you can also talk directly to NIST about their status regarding mode acceptance / AES mode adoption to resolve your FIPS issue. FFX has security evidence, an independent cryptographic overview, and is not a "new cipher." However, it is based on methods that return for 20 years - proven methods. In the implementation, we can encrypt data, preserving the length, structure, integrity, type and format. For example, specify an explicit formatting policy in which the output will be NNN-NN-NNNN.

So, as an AES mode, we can, for example, use the mainframe environment for implementation, we just use our own AES processor on z10. Similarly, on open systems with HSM devices, we can sit on top of an existing AES implementation.

The encryption preservation format (as is often mentioned) is thus already used in the industry and is available in finished products and is quickly deployed - it is already used in POS devices, etc., payment systems, enterprise deployments, etc.

Mark Bauer VP Product Management Voltage Safety Send a note to info@voltage.com for more information, or check out our website for more information.

0
source share

Something like Feistel's cipher should meet your requirements. Divide your input number into two parts (for example, 8 digits each), go through one part through an optionally reversible or bijective function, and subtract the other part from the result of this function (modulo, for example, 100,000,000). Then somehow change the numbers and repeat a bunch of times. Ideally, you need to slightly change the function that is used every time. Decryption is similar to encryption, except that one starts with canceling the last step of regrouping, and then subtracts the second part of the message from the result of using the last function used in the first part of the message (again, modulo 100,000,000), then cancels the previous step of regrouping etc.

The biggest difficulty with Feistel’s cipher is to find a function that provides good encryption with a reasonable number of rounds and finds out how many rounds it takes to achieve good encryption. If speed is not important, you could use something like AES to perform the scrambling function (since this should not be bijective, you can arbitrarily fill in data before each AES step and interpret the result as a large binary number modulo 100000000). Regarding the number of rounds, 10 is probably too few, and 1000 is probably overkill. I don’t know which value would be better.

0
source share

Use only 10 digits as input / output is completely unsafe. This is so uncertain that it will most likely be fixed in a real application, so consider using at least 39 digits (the equivalent of 128 bits). If you intend to use only 10 digits, it makes no sense to use AES in this case, a chance to invent your own (unsafe) algorithm.

The only way to get rid of this is to use the STREAM cipher. Use the 256-bit "SecureKey" key and the IV initialization vector, which should be different at each start of the starting season. Translate this number into a 77-digit (decimal) number and use the “add whit overflow” modulo 10 with each digit.

for example

  AES(IV,KEY) = 4534670 //and lot more secret_message = 01235 + and mod 10 --------------------------------------------- ciphertext = 46571 // and you still have 70 for next message 

when you finish for the numbers from stream encryption -> AES (IV, KEY) increase IV and repeat IV = IV + 1

Keep in mind that you should absolutely never use the same IV twice, so you should have a scheme to prevent this.

Another problem is creating threads. If you create a number in excess of 10 ^ 77, you must discard this increase in the number IV and retry the new IV. Another way is the high probability that you will have biased numbers and vulnerability.

It is also very likely that there are flaws in this scheme or will be in your implementation

-2
source share

All Articles