2
votes

Encryption and Decryption successful when encrypt with public key and decrypt with private key :

C# encryption with public key(Successful)

   public string EncryptData(string data) {

        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
        rsa.FromXmlString(xml); //public key

        var cipher = rsa.Encrypt(Encoding.UTF8.GetBytes(data), false);

        return Convert.ToBase64String(cipher );
    }

Java decryption with private key(Successful)

public static void decrypt() throws Exception{
    byte[] modulusBytes = Base64.getDecoder().decode(mod);
    byte[] dByte = Base64.getDecoder().decode(d);

    BigInteger modulus = new BigInteger(1, (modulusBytes));
    BigInteger exponent = new BigInteger(1, (dByte));

    RSAPrivateKeySpec rsaPrivKey = new RSAPrivateKeySpec(modulus, exponent);
    KeyFactory fact = KeyFactory.getInstance("RSA");
    PrivateKey privKey = fact.generatePrivate(rsaPrivKey);

    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    cipher.init(Cipher.DECRYPT_MODE, privKey);

    byte[] cipherData = Base64.getDecoder().decode(cipherByte);
    byte[] plainBytes = cipher.doFinal(cipherData);


    System.out.println(new String(plainBytes));
} 

Problem is Here

When c# encrypt with private key and java decrypt with public key bad padding error occur:

C# encryption with private key(Fail)

public stringEncryptData(string data) {

        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
        rsa.FromXmlString(xml); //private key

        var cypher = rsa.Encrypt(Encoding.UTF8.GetBytes(data), false);

        return  Convert.ToBase64String(cypher);
    }

java decryption with public key (Fail)

public static void decryptPublic() throws Exception{

    byte[] modulusBytes = Base64.getDecoder().decode(mod);
    byte[] expBytes = Base64.getDecoder().decode(exp);

    BigInteger modulus = new BigInteger(1, (modulusBytes));
    BigInteger exponent = new BigInteger(1, (expBytes));

    RSAPublicKeySpec pubKey = new RSAPublicKeySpec(modulus, exponent);
    KeyFactory fact = KeyFactory.getInstance("RSA");
    PublicKey publicKey = fact.generatePublic(pubKey);
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    cipher.init(Cipher.DECRYPT_MODE, publicKey );


    byte[] cipherData = Base64.getDecoder().decode(cipherByte);
    byte[] plainBytes = cipher.doFinal(cipherData);

    System.out.println(new String(plainBytes));
} 

I understand public key should use to do encryption and private key for decryption.But in my situation, i need to sent out public key to mutiple clients for decryption on a text encrypted by its private key. Text should be non readable by others except client. Can anyone see what problem on my code, or suggest a better solution to my problem.

2
Encrypt with the public key and decrypt with the private key. Give a copy of the private key to everyone who needs a copy to decrypt, but do not try to reverse the algorithm.WDS
@WDS As described in my answer, distributing the private key is also an extremely bad idea since you are then completely unable to control who those other parties may share the key with, and greatly increasing the difficulty of dealing with compromised keys.Iridium
@CY LIM: your encrypt and decrypt methods should be mirrored, meaning that if you use PKCS1 padding in your JAVA decrypt functions(Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")), you should also use PKCS1 padding in your C# encrypt functions var cypher = rsa.Encrypt(Encoding.UTF8.GetBytes(data), false); with var cypher = rsa.Encrypt(Encoding.UTF8.GetBytes(data), RSAEncryptionPadding.Pkcs1);. msdn.microsoft.com/en-us/library/mt132684%28v=vs.110%29.aspxgodvsdeity
"sent out public key to mutiple clients for" is wrong. On server side you need to encrypt with client public key and sign with server private key. Client will verify signature with server public key and decrypt with their own private key.AaA

2 Answers

1
votes

RSA encryption is only secure if a (secure) padding scheme is being used. RSA encryption schemes have been specified in PKCS#1 standards by RSA laboratories (now part of EMC2). These have been copied into RFC, such as RFC 3447: Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.1.

For the purposes of this document, an encryption scheme consists of an encryption operation and a decryption operation, where the encryption operation produces a ciphertext from a message with a recipient's RSA public key, and the decryption operation recovers the message from the ciphertext with the recipient's corresponding RSA private key.

So encryption with a private key is an undefined operation.


So what to do now:

  • securely distribute private keys instead of public keys
  • generate key pairs and securely transport the public key to the sender
  • if you require authentication/integrity instead of confidentiality, use signature generation instead of encryption

And, whatever you do, read into Public Key Infrastructure (PKI). It's a far stretching subject that you need to understand before you can apply it.

-1
votes

Encrypting with the private key/decrypting with the public key is a legitimate operation in RSA, however it is not used to protect data, it is instead used to authenticate the source of the data and its integrity. In this context the encryption operation is more usually called "signing".

Encrypting using the private key to protect data as you describe is insecure and so the fact that it is not easily done is likely intentional and intended to prevent incorrect use of the algorithm.

Distributing your private key to clients as suggested in the comments is also unwise since you have no control over who they may pass the key onto (accidentally or otherwise).

If you wish to encrypt data so that it can be decrypted by multiple distinct parties, then you should have each of them provide you with their own public key, and use that to encrypt the data separately for each client.