I have to create a signature from given data, but the problem is that data has length as key length. All implementation of RSA Signers in JAVA allow to put data of max. key length minus one length. How to create signature for data with length as key length? Algorithm is basic RSA without padding and without digest.
Firstly, please don't use RSA without padding - it's a terrible idea and diminishes the security of your system.
If you need to sign data that is equal in size to your key length (or larger), I'm afraid you'll need to use a digest. There's not really a choice here. I'm not sure why you wouldn't want to use a digest anyway.
RSA is only able to encrypt data to a maximum amount of your key size (2048 bits = 256 bytes) minus padding / header data (11 bytes for PKCS#1 v1.5 padding).
As a result it is often not possible to encrypt files with RSA directly. RSA is also not meant for this purpose. If you want to encrypt more data, you can use something like:
Generate a 256-bit random keystring K
Encrypt your data with AES-CBC with K
Encrypt K with RSA
Send both to the other side
Related
I use PBEWithHmacSHA256AndAES_128 in java for encryption and my question is about the algorithm internals.
I understand the roles of PBE, Hmac, and aes in encryption process.
My question is: does the Hmac digest the plaintext and then gets appended to the plaintext and get encrypted by aes (as in SSL)? because the result is always a multiple of aes 16 bytes (if i encrypt only 1 character i get 16 bytes as the final result) but Hmac is 32 bytes.
When i read about Hmac i found that the most used way is to digest the ciphertext and append the result to the ciphertext and save it, but it seems not the case in PBEWithHmacSHA256AndAES_128.
I am asking this because i don't want to save the password and rely on Hmac's result to check for password's validity, and also to understand better the algorithm.
(I sometimes calculate Hmac separately again by using PBKDF2WithHmacSHA1 with different salt and count for secret key generation and append the result to the final ciphertext for more security.)
From this on how to achieve password based encryption it is clear that i need to save salt, IV and cipher text in order to decrypt it later.
From this iv and salt can be stored along with cipher text
I am storing the hex value in this format
DatatypeConverter.printHexBinary(salt) + DatatypeConverter.printHexBinary(iv) + DatatypeConverter.printHexBinary(ciphertext);
Do i need to store the values in Binary format ?
DatatypeConverter.printBase64Binary(salt) + DatatypeConverter.printBase64Binary(iv) + DatatypeConverter.printBase64Binary(ciphertext));
output clearly indicates the where the salt , iv is ending which is awful
lIvyAA/PZg4=fE4gTZUCPTrKQpUKo+Z1SA==4/gAdiOqyPOAzXR69i0wlC7YFn9/KOGitZqpOW2y3ms=
Will storing in hex format have any effects of data loss ?
Will the length of IV is constant ? in my case it is always 32 characters (hexadecimal)
Or i need to even store length of IV as well ? as the salt length is fixed initially to 8 bits (16 hexadecimal characters)
(I am using PBKDF2WithHmacSHA1 algorithm for key generation and AES/CBC/PKCS5Padding for cipher)
I think it is worth emphasizing again what the accepted answer above mentioned in passing.
That is, it is unnecessary and unwarranted to make any attempt to hide the salt or the IV. The security of your cryptography is entirely dependent on the secrecy of the secret key, and that of the secret key alone. The IV and the salt can be handed out in clear text along with the ciphertext, and as long as the secret key remains a secret, the ciphertext remains secure.
It's important to understand and accept that, or you will wind yourself about an axle trying to obfuscate things that don't matter. There is no security in obscurity.
It is important to note, however, that the salt should be generated in a cryptographically strong pseudorandom number generator. A new salt should be generated for each new plain text that is being encrypted. Likewise, the IV should be randomly generated for each new ciphertext.
Those parameters need to be independent and unpredictable but need not be secret.
So you can store them in separate fields or delimit them in a single field, or use fixed lengths for the first two of three fields. For maximum flexibility and future proofing, though, I suggest delimited fields, and include all parameters needed to deal with the data. If you are using PBE, I would include the algorithm name and the iteration count, too, rather than rely on default values.
Base64 encodes in chunks of 3 bytes into 4 base64 chars. If the number of bytes that needs to be encoded ain't a multiplum of 3 the last block is padded with one or two =, to indicate that this block ain't full 3 bytes.
As neither the salt nor the IV needs to be kept secret, there really ain't any problem about being able to detect where they start or stop. The base64 padding char = ain't a problem - but you ought to have a way to separate the three encoded strings. You could e.g. simply seperate the parts with a :.
The size of the IV is the same as the block size of your encryption algorithm. In this case you use AES that have a block size of 128 bits, which is 16 bytes. This would give 32 bytes if hex encoded, or 24 bytes if base64 encoded. Salt don't really have a fixed length, and will depend on your implementation.
I'm dealing with a legacy application that uses a custom protocol to cipher communication. Random AES keys are generated in legacy Java app like this:
keygen = KeyGenerator.getInstance("AES");
keygen.init(128);
keygen.generateKey().getEncoded();
I've been looking for solutions on crypto with no luck. How can I generate this key on nodejs?
That code probably does not do as much as you think. It simply generates 16 (128 / 8) secure random bytes, then wraps a key object around it. So with nodejs, you simply generate 16 bytes and feed the algorithm the raw key data.
If you want to use the generated key, then make sure you create a binary encoded string or buffer from the bytes returned by the getEncoded() method. You could use hexadecimal encoding/decoding if you require the key to be a textual string somewhere in the process.
See randomBytes() and createCipheriv() for information.
AES keys are just cryptographically strong random bytes, DES (parity bits) and RSA (prime number calculation) keys are not.
I want that encrypted data have the same length as my original text, because I must respect the constraint of length. I am using BouncyCastle.
Here's my code to generate the keys pair:
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(512);
KeyPair keypair = keyGen.genKeyPair();
PublicKey pub = keypair.getPublic();
byte[] pubs = pub.getEncoded();
And here's my code to encrypt:
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
PublicKey pk = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(pubs));
cipher.init(Cipher.ENCRYPT_MODE, pk);
byte[] cipherBytes = cipher.doFinal(plainArray);
The encoded data is very large, what can I do to make as small as original data ?
Nothing, at least not regarding the RSA. RSA requires a certain amount of padding to be secure, and as the data will be seen as random data by any compression method, you cannot compress it either.
Of course, you should not directly encrypt data directly using RSA, you should encrypt a random session/data key instead. But even then, you will have the encrypted session key as overhead.
You can remove some bits for the asymmetric encrypted data/key by using Elliptic Curve Cryptography (the output of which is double the key size minimum, but key sizes are much smaller to achieve the same level of security). EC cryptography is not for the meek though, it has lots of complexity.
512 bit RSA is considered insecure by the way. Use 1024 as minimum or keep to the ECRYPT II or NIST recommendations listed at http://www.keylength.com/ .
If you can keep the key secret, you can use a symmetric cryptosystem like AES. If used in CFB mode, it can be adapted to any bit length. I.e. #bits input & output is identical.
RSA and ElGamal -- the main public-key cryptosystems-- can be broken in a matter of hours even at 512 bits as you are selecting. 1024 - 4096 bits is normal. Less than 512 bits is worthless unless your opponent is limited to using 1990s hardware. :-)
The nature of RSA is such that you use exponentiation in encryption and decryption.
Basically, for public key e and private key d, you take a message m and then you get a compressed message equal to c=m^e and mod it by n. Then you decrypt with m=c^d and again mod it by n (mod means take the remainder).
If you think about it, a message to the power of something results in a larger number. Because you do a mod n, you end up with a number that is at most n-1. n is the key length.
So basically, whatever message you take, you encrypt to something as large as n. The message has to be less than n.
But the message has to be turned into an integer using a padding scheme (so you can do the exponentiation). This padding scheme may require less than n bits. And so, you end up with larger files than the size of the data being encrypted. Also, the last chunk may be less than n bits, but will encrypt into size n.
I'm currently working on a protocol, which uses Diffie-Hellman for an key exchange.
I receive a packet, which consists of an aes-128 encrypted part and a 128 Bit DH Public Key.
In a very last step in the protocol, the aes key is sent to another peer in the network.
This aes-key should be encrypted with a cipher using a 128 bit strong secretkey.
I plan to use Blowfish (can also be another cipher, doesn't really matter for the problem)
Now to encrypt the aes-key, with lets say blowfish, I have to build a secretkey for the encryption with a class called SecretKeySpec (I'm using javax.crypto stuff), which takes an byteArray in the constructor to build the secretKey.
The sharedkey from DH is a 128 Bit BigInteger.
Well, now I can interpret my shared-key as a byteArray (wich gives me still 128 Bit in 16Bytes [where the numbers are interpreted as frames of 8 Bit data])
So my question is, how strong is my key really?
Is there any impact because I only use numbers as input for the byteArray (so does this limit the keyspace in any way?)
I think this is not the case, but I'm not 100% sure.
Maybe someone can do the math and proof me right or wrong.
If I'm wrong what keysize for the shared key give me piece of mind to finally get to the 128Bit SecretKey for the encryption?
The Crypto++ website suggests using a minimum p of 3072 bits (or 256 bits for an ECC implementation) to transport a 128 bit AES key.
You might wish to study the references provided at http://www.keylength.com/en/compare/ for further information about comparing key lengths among different algorithms.
Not an expert in DH here, but to me it seems that DH's keyspace for the shared key represented in n bits is somewhat smaller than 2^n.