I know its not the usual thing to do. But the specification I'm implementing is discribed this way, and I cannot run out.
I was trying to encrypt the modulus and exponent of the private key, but the following test code raises an exception becaus开发者_如何学Pythone the byte array is 1 byte larger then the maximum allowed by RSA block:
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import javax.crypto.Cipher;
import org.apache.commons.lang.ArrayUtils;
public class TEST {
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");
keyPairGenerator.initialize(1024);
return keyPairGenerator.generateKeyPair();
}
public static void main(String[] args) throws Exception {
KeyPair keyPair = generateKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
System.out.println("Priv modulus len = " + privateKey.getModulus().bitLength());
System.out.println("Priv exponent len = " + privateKey.getPrivateExponent().bitLength());
System.out.println("Priv modulus toByteArray len = " + privateKey.getModulus().toByteArray().length);
byte[] byteArray = privateKey.getModulus().toByteArray();
// the byte at index 0 have no value (in every generation it is always zero)
byteArray = ArrayUtils.subarray(byteArray, 1, byteArray.length);
System.out.println("byteArray size: " + byteArray.length);
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
Cipher cipher = Cipher.getInstance("RSA", "BC");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedBytes = cipher.doFinal(byteArray);
System.out.println("Success!");
}
}
(obs. its just a test, i would never encrypt the private key with its pair public key)
The byte array is 128 bytes, the exactly maximum allowed by a RSA block, so why the exception? And how to fix it?
EDIT: if I initilize the key pair generator with 1023 (instead of 1024) it works, but isn't the usual for RSA key size 1024?
First: Someone has written this specification. Check with them instead of asking us. They have some reason for writing this requirement and you need to know what it is. When facing an unclear requirement the worst thing you can do is to begin guessing - especially when handling cryptography.
Second: in your test-code you are encrypting the private key modulus. The modulus is not secret in the RSA crypto-system, so there should be no need to encrypt this. You are not attempting to encrypt the private exponent (which is the actual secret part). The private exponent is always smaller than the modulus, so you should be able to encrypt it using the raw RSA operation (if you make sure to remove the prepended zero). This should be secure (translation: I do not see any obvious attacks considering it for 30 seconds) - if non-standard.
EDIT: As GregS points out in the comments, you cannot be sure that the private exponent of the key you want to encrypt is smaller than the modulus of the key you want to use to encrypt with. I think approximately 25% of the time this will not be the case. So use the method below instead.
An even better way to do it (which is completely standard and which I suspect is what the specification-writers actually intends) would be to encrypt the private key using the usual hybrid approach: Generate a symmetric key, use it to encrypt the private key (here you can use a standard serialized format without having to worry about the length), encrypt the symmetric key with the other public key (using RSA/PKCS#1) and transmit the two encryptions to the recipient who performs the opposite steps.
Are you sure you need to do this? Most people encrypt symmetric keys with RSA key but encrypting RSA inside RSA doesn't buy you anything.
The maximum size of clear text can be encrypted by RSA is
(key_size/8) - 11 bytes
So you can only encrypt 117 bytes for 1024-bit key. You need to use a much larger key to encrypt a smaller key.
If you absolutely want to use your own crypto protocol (which usually is not a good idea) then you could keep the public key (i.e. the modulus N and the public key e) as plaintext and simply encrypt one of the factors N. Since the facotors are about 512 bits for a a 1024 bit modulus, you should not have a problem with the encrytion. Knowing one of the factors and the public key is enough to determine the remainder of the private key.
The PKCS#1 method adds 11 bytes of checksums and padding, so your maximum plain-text size will be 117 bytes. See Too much data for RSA block fail. What is PKCS#7?
The amount of data you can encrypt in RSA is equal to the key size - 11 bytes. If you want to store more data, you should increase your key size from 1024.
The answer I was looking was (almost hidden) in the project's specification. Its to encrypt the rsa key by parts, and concatenate the parts. The same to decrypt (of course the size will need to be a default size known by encryptor and decryptor). This way I can use RSA without any symmetric key (not that I agree that this is the best encryption method).
Sorry trouble you guys (I tried to delete this question, but it cannot be deleted now).
精彩评论