I want to encrypt/decrypt digits into string (with only digits and/or upper characters) with the same length using Format-preserving Encryption. But I don't find implementation steps. So, can anyone please provide WORKING sample for C# 2.0?
For an example,
If I encrypt fixed length plaintext like 99991232 (with or without fixed key) then the cipher should be like 23220978 or ED0FTS. If the length of encrypted string is less than plain text then also it would be all right. But cipher text length must not be greater than plain text and the cipher text must of of fixed length.
From your question I assume that the plain text is numeric, where the cipher text could be alphanumeric. Due to this it is quite easy to make an encoding scheme. This makes your format preservation less stringent and this can be taken advantage of (this won't work if your plain text is also alphanumeric).
First, find a power of 2 that is greater than the number of discrete values that you have, for example, in the numeric case you have 10 discrete values - so you would use 16 (2 ^ 4). Create a 'BaseX' encoding scheme for this (in this case Base16) and decode the plain text to binary using it.
Thus given the plain text:
1, 2, 3, 4
We encode it to:
0001-0010 0011-0100
You can then run this through your length-preserving cipher (one example of a length-preserving cipher is AES in counter mode). Say you get the following value back:
1001-1100 1011-1100
Encode this using your 'BaseX' encoder, and in our case we would get:
9, C, B, C
Which is the same length. I threw together a sample for you (bit large to paste here).
As Henk said, "Format Preserving Encryption" is not defined. I can think of two possible answers:
Use AES and convert the cyphertext byte array to a hex string or to Base64.
Use a simple Vigenère cipher just replacing the characters you want to replace.
You need to specify your requirement more clearly.
ETA: You do not say how secure you need this to be. Standard Vigenère is not secure against any sort of strong attack, but will be safe from casual users. Vigenère can be made absolutely secure, but that requires as much true random key material as there is plaintext to encypher, and is usually impractical.
Related
walking through some cryptogtaphy stuff , I saw that RNGCryptoServiceProvider has 2 methods :
link
RNGCryptoServiceProvider.GetNonZeroBytes
and
RNGCryptoServiceProvider.GetBytes
And so I ask :
What is odd with Filling an array of bytes with a cryptographically strong sequence of random value which some (0 or more) of them are zeros ?
(it is random values and apparently there wont be many zeros , and still zero is also a regular number)
why did they created the distinguishing ?
Within the .NET framework, GetNonZeroBytes(byte[]) is used when generating PKCS#1 padding for RSA encryption, which uses 0x00 as a seperator.
Using a tool like Reflector, you can see it used in RSAPKCS1KeyExchangeFormatter.CreateKeyExchange(byte[]) to implement padding as per RFC 2313, section 8.1.2 (RFC 3218 has some nice ASCII art that demonstrates the byte layout more clearly).
GetNonZeroBytes(byte[]) could also be used to generate salt. The Cryptography StackExchange site has a similar question which suggests that avoiding 0x00 is to help with libraries and APIs that may treat the salt as a zero-terminated string, which would accidentally truncate the salt. However, unless one is using P/Invoke, this is unlikely to be a concern in .NET.
I have try to generate unlock key like XXXX-XXXX-XXXX or simply small length string or Hexstring. I am using RSA algorithm to encrypt and decrypt the Key. I got some long string like
Q65g2+uiytyEUW5SFsiI/c5z9NSxyuU2CM1SEly6cAVv9PdTpH81XaWS8lITcaTZ4IjdmINwhHBosvt5kdg==
when I convert the byte array (array size is 64 byte) using the below convert method.
Convert.ToBase64String(bytes);
My requirement is to generate the minimal length Key. Is there any way to convert the Byte array (array size is 64 byte) to minimal length and I need that back to byte array or any other suggestions (to minimize the string length) would be helpful.
I have tried to convert the output string to Hex decimal, but the output is too long than the string.
You may want to take a look at What is the most efficient way to encode an arbitrary GUID into readable ASCII (33-127)? There the Base 85 encoding is discussed which is used to compress PDF files.
Though, the difference between Base64 and Base85 in your case is 8 characters.
You can safely remove trailing '==' in Base64 string because it is used for alignment and will always be there for 64-byte values (Of course you will have to add these characters back to decode the string).
Since you mention you want users to be able to type in the string,
there will be an inverse correlation between easy-of-use from point of view of users and the length of string.
Even typing a Base64 string is prone to lot of errors. Base32 strings are much easier to type, but correspondingly the length will increase.
If the users can Copy-Paste the key, then the above is moot and there should not be any valid reason why the length of the string should be as small as possible.
Obviously, you can only fit a certain amount of data into a fixed number of characters. You have pretty much maxed out the limit with base64 already which gives you 6 bits per byte.
Therefore you need to reduce the amount of data that needs to be stored. Can you reduce the key length? You could use a 96 bit key (by always leaving all other bytes zero). That would require 16 base64 characters which is much better.
It seems you don't need much security against brute forcing. So you can reduce the key size even further.
I'm using HMACSHA512 to hash data using a shared key. Since the key is shared I'd like for it to be all printable characters for ease of transport. I'm wondering what the best approach is to generating these keys.
I'm currently using the GetBytes() method of RNGCryptoServiceProvider to generate a key, but the byte array it returns contains non-printable characters. So I'm wondering if it is secure to base64 encode the result or does that erode the randomness too much and make things much less secure? If that isn't a good approach can you suggest one?
I do understand that by limiting the keys to printable characters I am limiting the overall breadth of the key space (ie: lopping off 1 of the 8 bits), but I am OK with that.
If you can handle not auto-generating the key then http://www.grc.com/passwords is a good source of VERY random key material.
Base64 wouldn't reduce the underlying entropy of the byte array. You could generate the key and use it in its raw form, but Base64 encode it to transport it to where you need it to be. You'd then Base64 decode it back to the raw form before you use it in the new location. There is no loss of entropy in this operation. The Base64 encoding reduces the entropy to 6-bits per byte instead of 8, but the result of the coding is longer, so overall the entropy is the same.
The other way you could do it would be to get 24 random bytes for 192-bits worth of entropy. Base64 encoding this would give you a 32 character string (256-bits) which still has the original randomness and 192-bits of entropy. You could use this as your shared key directly.
BASE64 transforms a byte sequence so it uses only certain printable characters.
This transformation does not change the information in any way, just how it is stored. It is also reversible: you can get the original byte sequence by decoding the BASE64 output.
So using BASE64 does not "erode the randomness" or limit the key space in any way.
I need a library/tool/function that compresses a 50-60 char long string to smaller.
Do you know any?
Effective compression on that scale will be difficult. You might consider Huffman coding. This might give you smaller compression than gzip (since it will result in binary codes instead of a base-85 sequence).
Are you perhaps thinking of a cryptographic hash? For example, SHA-1 (http://en.wikipedia.org/wiki/SHA-1) can be used on an input string to produce a 20-byte digest. Of course, the digest will always be 20 bytes - even if the input string is shorter than 20 bytes.
The framework includes the GZipStream and DeflateStream classes. But that might not really be what you are after - what input strings have to be compressed? ASCII only? Letters only? Alphanumerical string? Full Unicode? And what are allowed output strings?
From an algorithmic stand point and without any further knowledge of the space of possible inputs I suggest to use arithmetic coding. This might shrink the compressed size by a few additional bits compared to Huffman coding because it is not restricted to an integral number of bits per symbol - something that can turn out important when dealing with such small inputs.
If your string only contains lowercase characters between a-z and 0-9 you could encode it in 7bits.
This will compress a 60 char string to 53 bytes. If you don't need digits you could use 6bits instead, bringing it down to 45 bytes.
So choosing the right compression method depends on what data your string contains.
You could simply gzip it
http://www.example-code.com/csharp/gzip_compressString.asp
I would use some basic like RLE or shared dictionary based compression followed by a block cipher that keeps the size constant.
Maybe smaz is also interesting for you.
Examples of basic compression algorithms:
RLE
(Modified or not) Huffman coding
Burrows-Wheeler transformation
Examples of block ciphers ("bit twiddlers"):
AES
Blowfish
DES
Triple DES
Serpent
Twofish
You will be able to find out what fullfills your needs using wikipedia (links above).
I was working on some encryption/decryption algorithms and I noticed that the encrypted byte[] arrays always had a length of 33, and the char[] arrays always had a length of 44. Does anyone know why this is?
(I'm using Rijndael encryption.)
Padding and text encoding. Most encryption algorithms have a block size, and input needs to be padded up to a multiple of that block size. Also, turning binary data into text usually involves the Base64 algorithm, which expands 3 bytes into 4 characters.
That's certainly not true for all encryption algorithms, it must just be a property of the particular one you're using. Without knowing what algorithm it is, I can only guess, but the ratio 33/44 suggests that the algorithm might be compressing each character into 6 bits in the output byte array. That probably means it's making the assumption that no more than 64 distinct characters are used, which is a good assumption for plain text (in fact, that's how base64 decoding works).
But again, without knowing what algorithm you're using, this is all guesswork.
Without knowing the encryption you're using, its a little tough to determine the exact cause. To start, here's an article on How to Calculate the Size of Encrypted Data. It sounds like you might be using a hash of your plaintext, which is why the result is shorter.
Edit: Heres the source for a Rijndael Implementation. It looks like the ciphertext output is initially the same length as the plaintext input, and then they do a base64 on it, which, as the previous poster mentioned, would reduce your final output to 3/4 of the original input.
No, no idea at all, but my first thought would be that your encryption algorithm is built such that it removes 1 bit per 10 from the output data.
Only you can know for sure since we cannot see you code from out here :-)
It would be a pretty lousy encryption algorithm if it was just replacing bytes one-for-one. That was state of the art 50 years ago, and it didn't work very well even then. :)