I would like to sign a device, and I have 64 bits to store my signature in the device. This device has a MAC address and some other details (about 30 bytes worth) I can mangle to create my signature.
If possible, I would like the method to be one-way, so that I can verify that the signature is valid without knowing how to create a valid signature. Most public-private keys have this feature but they generate signatures that are 48 bytes long (I only have 8 bytes).
Implementation in Python is a plus.
Thanks
EDIT:
Thanks for the advice everyone. It sounds like there is no secure way to do this, only a way that is moderately inconvenient to attackers. I'll probably use a cryptographic hash combined with secret bit-shuffling. This will be as secure as any other link in my (very weak) 'security'.
Hash functions and digital signatures are very different things.
The size of a digital signature depends on the underlying hash function and the key length. So in theory, you can create an RSA implementation that generates 64-bit signatures, but that'd be an extremely weak signature.
For smaller key lengths, you might want to look at elliptic curve cryptography.
EDIT: Yes, I'm a cryptographer.
EDIT 2: Yet if you only need a hash function, you can look at elf64 or RIPEMD-64 as Fernando Miguélez suggested.
EDIT 3: Doing the math, you'd need to use 16-bit keys in ECC to generate 64-bit signatures, which is very weak. For ECC, anything less than 128 bits can be considered weak. For RSA this is 1024 bits.
Basically what you need is a 64-bit cryptographic hash funcion, such as Ripemd-64 or elf-64. Then you encrypt the hash with a cryptographic method and you got a 64 bit signature. The only problem is, from the point of view of a non-cryptoanalyst, that 64 bit offers a much weaker signature than typical over-128 bit hash. Nonetheless it could still be suitable for your application.
You could just use a standard hashing function (MD5 SHA1) and only use the first or last 30 bytes.
The number of bytes a hashing function generates is fairly arbitrary - it's obviously a trade off between space and uniqueness. There is nothing special about the lenght of the signature they use.
Edit - sorry I was thinking that MD5 returned 32bytes- it actaulyl returns 16bytes but is ussually written as 32hex digits.
Related
Is there a function that generates a hash that has the exact lenght I want? I know that MD5 always has 16 bytes. But I want to define the lenght of the resulting hash.
Example:
hash('Something', 2) = 'gn'
hash('Something', 5) = 'a5d92'
hash('Something', 20) = 'RYNSl7cMObkPuXCK1GhF'
When the length increases, the result should be more secure from duplicates.
The upcoming SHAKE256 (or SHAKE128 for a security level of 128bit instead of 256bit), a so called extendable-output function (XOF), is exactly what you are looking for. It will be defined alongside with SHA3. There is already a draft online.
If you need an established solution now, follow CodesInChaos advice and truncate SHA512 if a maximum of 64byte is enough and otherwise seed a stream cipher with the output of a hash of the original data.
Technical disclaimer: After an output length of 512bit the "security against duplicates" (collision resistance) does not increase any more with longer output, as with SHAKE256 it has reached the maximum security level against collisions the primitive supports (256bit). (Note that because of the birthday paradox the security level of an ideal hash function with output length of n bit against collisions is only n/2 bit.) Any higher security level is pretty much meaningless anyway (probably 256bit is already an overkill) given that our solar system does not provide enough energy to even count from 0 to 2^256.
Please do not confuse "security levels" with key lengths: With symmetric algorithms one usually expects a security level equal to the key size, but with asymmetric algorithms the numbers are completely unrelated: A 512 bit RSA encryption scheme is far less secure than 128bit AES (i.e. 512bit RSA moduli can be factored by brute force already).
If a cryptographic primitive tries to achieve a "security level of n bits" it means that there are supposed to be no attacks against it that is faster than 2^n operations.
BLAKE2 can produce digests of any size between 1 and 64 bytes.
If you want a digest considered cryptographically secure, consider the Birthday problem and what other algorithms use — e.g. SHA-1 uses 20 bytes and is considered insecure, SHA-2 uses 28/32/48/64 bytes and is generally considered secure.
If you just want to avoid accidental collisions, still consider the Birthday problem (above), but 16 or even 8 bytes might be considered sufficient depending on the application (see table).
I need to sign a small string with an asymmetric key encryption scheme.
The signature will be stored on a small chip together with the signed string. I have very little space to spare (about 60bytes for signature + string), so the generated signature should be as small as possible.
I looked around for how to do it, and what I found is that I could use RSA-SHA1, but the generated signature with a 512 bit key is 64 bytes. That is a bit much.
What secure algorithm could I use to generate a small asymmetric signature?
Would it still be secure if I store the SHA1 sum of the RSA-SHA1 signature, and later verify that instead?
What you're bumping up against here is one of the properties of a good hash function - the return value should be long to protect against birthday attacks (where two different inputs result in the same output hash). Generally 128-512 bits is preferred hence the SHA-1 signature gives you 512 bits.
As with all things in cryptography security is a trade off. As you are using asymmetric signing have you considered using RSA-MD5 as your signature option? This will give you a far shorter return of 128 bits but this comes with the caveat that MD5 is considered broken and is generally being moved away from.
XOR encryption is known to be quite weak. But how weak is it if I have a key that is made up of multiple keys of different (ideally prime) lengths which are combined to make a longer key. eg I have a text keys of length 5, 9 and 11. If I just apply the first key using XOR encryption then it should be easy to break as the encryption byte will repeat every 5 bytes. However if I 'overlay' the 3 of these keys I get an effective non-repeating length of 5*9*11 = 495. This sounds to me pretty strong. If I use a couple of verses of a poem using each line as a key then my non-repeating length will be way bigger than most files. How strong would this be (providing the key remains secret! :) )
XOR encryption is exactly as strong as the key stream. If you XOR with a "One time pad" - a sequence of physically generated random numbers that you only use once, then your encryption is theoretically unbreakable. You do have the problem however of hiding and distributing the key.
So your question comes down to - "how secure/random is a keystream made of three text strings?" The answer is "not very secure at all". Probably good enough to keep out your little sister, but not necessarily if you've got a smart little sister like I have.
What about the 'known plaintext' attack? If you know the encrypted and the cleartext versions of the same string, you can retrieve the key.
http://en.wikipedia.org/wiki/XOR_cipher
http://en.wikipedia.org/wiki/Known-plaintext_attack
http://en.wikipedia.org/wiki/Stream_cipher_attack
If P and Q are two independent cryptographic methods, the composite cryptographic function P(Q(x)) won't be any weaker than the stronger of P(x) or Q(x), but it won't necessarily be meaningfully stronger either. In order for a composite cryptographic function to gain any strength, the operations comprising it have to meet certain criteria. Combining weak ciphers arbitrarily, no matter how many one uses, is unlikely to yield a strong cipher.
Many of the encryption techniques I've seen can easily encrypt a simple 8 digit number like "12345678" but the result is often something like "8745b34097af8bc9de087e98deb8707aac8797d097f" (made up but you get the idea).
Is there a way to encrypt this 8 digit number but have the resulting encrypted value be the same or at least only a slightly longer number? An ideal target would be to end up with a 10 digit number or less. Is this possible while still maintaining a fairly strong encryption?
Update: I didn't make the output clear enough - I am wanting an 8-digit number to turn into an 8-digit number, not 8 bytes.
A lot here is going to depend on how seriously you mean your "public-key-encryption" tag. Do you actually want public key encryption, or are you just taking that possibility into account?
If you're willing to use symmetric encryption, producing 8 bytes of output from 8 bytes of input is pretty easy: just run 3DES in ECB (Electronic Code Book) mode, and that's what you'll get. The main weakness of ECB is that a given input will always produce the same result, so if your inputs might repeat an attacker will be able to see that repetition, and may be able to notice a pattern of "encrypted value X leads to action Y", even if they can't/don't break the encryption itself at all. If you can live with that, 3DES/ECB is probably your answer.
If you can't live with that, 3DES in CFB mode is probably the next best. This will produce 16 bytes of output from 8 bytes of input (note that it's not normally doubling the input size, but adding 8 bytes to the input size).
3DES is hardly what anybody would call a cutting edge algorithm, but I'd say it still qualifies as "fairly strong encryption". Part of its weakness as an algorithm stems from its relatively small block size, but that also minimizes expansion of the output.
Edit: Sorry, I forgot to the public-key possibility. With most public-key cryptography, the smallest result is roughly equal to the key size. With RSA encryption, that'll typically mean a minimum of something like 1024 bits (and often considerably more than that). To keep the result smaller, I'd probably use Elliptical Curve Cryptography, for which a ~200 bit key is reasonably secure against known attacks. This will still be larger than 3DES/CFB, but not outrageously so.
Well you could look a stream cipher which encrypts bytes 1:1. With N bytes input, there are N bytes encrypted/decrypted output. Such ciphers are usually based on an algorithm that creates a stream of random numbers, with the encryption key/IV acting as seed.
For some stream ciphers, look at the eSTREAM candidates. I don't know of any relevant attacks on HC-128 and HC-256, for example.
I'm having a bit of difficulty getting an understand of key length requirements in cryptography. I'm currently using DES which I believe is 56 bits... now, by converting an 8 character password to a byte[] my cryptography works. If I use a 7 digit password, it doesn't.
Now, forgive me if I'm wrong, but is that because ASCII characters are 7 bits, therefor 8 * 7 = 56bits?
That just doesn't seem right to me. If I want to use a key, why can I not just pass in a salted hash of my secret key, i.e. an MD5 hash?
I'm sure this is very simple, but I can't get a clear understanding of what's going on.
DES uses a 56-bit key: 8 bytes where one bit in each byte is a parity bit.
In general, however, it is recommended to use an accepted, well-known key derivation algorithm to convert a text password to a symmetric cipher key, regardless of the algorithm.
The PBKDF2 algorithm described in PKCS #5 (RFC 2898) is a widely-used key derivation function that can generate a key of any length. At its heart, PBKDF2 is combining salt and the password through via a hash function to produce the actual key. The hash is repeated many times so that it will be expensive and slow for an attacker to try each entry in her "dictionary" of most common passwords.
The older version, PBKDF1, can generate keys for DES encryption, but DES and PBKDF1 aren't recommended for new applications.
Most platforms with cryptographic support include PKCS #5 key-derivation algorithms in their API.
Each algorithm is designed to accept a certain key length. The key is used as part of the algorithm, and as such, can't be whatever your heart desires.
Common key sizes are:
DES: 56bit key
AES: 128-256bit key (commonly used values are 128, 192 and 256)
RSA (assymetric cryptography): 1024, 2048, 4096 bit key
A number, such as 1234567 is only a 4-byte variable. The key is expected to be a byte array, such as "1234567" (implicitly convertible to one in C) or `{ '1', '2', '3', '4', '5', '6', '7' }.
If you wish to pass the MD5 hash of your salted key to DES, you should use some key compression technique. For instance, you could take the top 7 bytes (somewhat undesirable), or perform DES encryption on the MD5 hash (with a known constant key), and take all but the last byte as the key for DES operation.
edit: The DES I'm talking about here is the implementation per the standard released by NIST. It could so be (as noted above), that your specific API expects different requirements on the length of the key, and derives the final 7-byte key from it.
The key must have size 64-bits but only 56-bits are used from the key. The other 8-bits are parity bits (internal use).
ASCII chars have 8-bit size.
You shouldn't pass you passwords straight into the algorithm. Use for instance the Rfc2898DeriveBytes class that will salt your passwords, too. It will work with any length.
Have a look here for an example.
EDIT: D'Oh - your question is not C# or .Net tagged :/
According to MSDN DES supports a key length of 64 bits.
To avoid this issue and increase the overall security of one's implementation, typically we'll pass some hashed variant of the key to crypto functions, rather than the key itself.
Also, it's good practice to 'salt' the hash with a value which is particular to the operation you are doing and won't change (e.g., internal userid). This assures you that for any two instances of the key, the resulting has will be different.
Once you have your derived key, you can pull off the first n-bites of it as required by your particular crypto function.
DES requires a 64 bit key. 56 bits for data and 8 bits for parity.
Each byte contains a parity bit at the last index. This bit is used to check for errors that may have occurred.
If the sum of the 7 data bits add up to an even number the correct parity bit is 0, for an odd number it's 1.
ASCII chars contain 8 bits, 8 chars can be used as a key if error correction is not necessary. If EC is necessary, use 7 chars and insert parity bits at indices (0 based) 7,15,23,31,39,47,55,63.
sources:
Wikipedia: https://en.m.wikipedia.org/wiki/Data_Encryption_Standard
“The key ostensibly consists of 64 bits; however, only 56 of these are actually used by the algorithm. Eight bits are used solely for checking parity, and are thereafter discarded. Hence the effective key length is 56 bits.”
“The key is nominally stored or transmitted as 8 bytes, each with odd parity. According to ANSI X3.92-1981 (Now, known as ANSI INCITS 92-1981), section 3.5:
One bit in each 8-bit byte of the KEY may be utilized for error detection in key generation, distribution, and storage. Bits 8, 16,..., 64 are for use in ensuring that each byte is of odd parity.”