2

Node.js code for encryption

   function encrypt(msg) {
        try {
            const public_key = fs.readFileSync(path.join(__dirname, 'PublicKey.pem'), 'utf8');
            const encryptStr = crypto.publicEncrypt({
                key: public_key,
                padding: crypto.constants.RSA_PKCS1_PADDING
            }, Buffer.from(msg,'utf8'));
            let encryptString = encryptStr.toString('hex');
            return encryptString;
        } catch (e) {
            console.log(e);
            return false;
        }
    }

Android Code for decryption

  public static String decryptStringWithPrivateKey(String s, String keyFilename)  throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        PrivateKey pkey = readPrivateKeyFromPem(keyFilename);

        cipher.init(Cipher.DECRYPT_MODE, pkey);
        String dec = new String(cipher.doFinal(Base64.getDecoder().decode(s)), "UTF-8");

        return dec;
    }


   public static PrivateKey readPrivateKeyFromPem(String keyFilename) throws Exception {
        byte[] keyBytes = Files.readAllBytes(new File(keyFilename).toPath());
        String keyString = new String(keyBytes);

        if (keyString.contains("BEGIN PRIVATE KEY")) {
            return readPrivateKeyFromPem_PKCS8(keyFilename);
        }
        else if(keyString.contains("BEGIN RSA PRIVATE KEY")){
            return readPrivateKeyFromPem_PKCS1(keyFilename);
        }
     
        throw new Exception("Unknown private key format in "+keyFilename);
    }

I want to encrypt api on server side and decrypt the data on android device to avoid unauthorized access.

while decryption on android "Input byte array has incorrect ending byte at 172" this one error are thrown.

2 Answers 2

2

In the NodeJS code the cipher text is hex encoded and in the Java code it is Base64 decoded. This must be made consistent, either Base64 or hex encoding on both sides.

Also, in the Java code, when instantiating the cipher, only the algorithm is specified. This results in a default padding being used, which e.g. on my machine (API 28, Android 9 Pie) corresponds to RSA/ECB/NoPadding. This is not compatible with the NodeJS side, which uses PKCS#1 v1.5 padding (besides that RSA without padding, so called textbook RSA, is insecure). Therefore, padding must also be specified in the cipher instantiation with RSA/ECB/PKCS1Padding.

Using a private key in PKCS#8 format and an own implementation of readPrivateKeyFromPem_PKCS8() both codes work on my machine if the two bugs mentioned above are fixed. However, the methods not posted could also contain flaws.

Sign up to request clarification or add additional context in comments.

6 Comments

Can you Please Provide some Example Code ?
This is for short data Encryption or Decryption Is there any method where we can Encryption or Decryption a large amount data
@VishalSarvaiya - With RSA only data can be encrypted, whose length is at most as large as the key size (actually even less, since a part of the space is reserved by the padding), e.g. a message with a 2048 bits key may be only 245 bytes long for PKCS#1 v1.5 padding (here). For larger data hybrid encryption is used, i.e. here the data is encrypted with a symmetric algorithm like AES and the symmetric key is encrypted with an asymmetric algorithm such as RSA.
Thanks for your replay I got your point. As above Can you give me one of example for that please ? So I can make it so clear..
@VishalSarvaiya - This is a larger effort and should be addressed in a separate question. However, you should first search the web or SO to see if there are any posts on this subject, e.g. an-example-using-a-hybrid-cryptosystem-consisting-of-oaep-and-gcm.
|
0

using node rsa plugin i found below soliton.

 import forge from 'node-forge';
    
    const publicKey: any = process.env['NEXT_PUBLIC_PUBLIC_KEY']
    
    const publicKe = forge.pki.publicKeyFromPem(publicKey);
    
        // const privateKe = forge.pki.privateKeyFromPem(y);
    
    const encryptedBytes = publicKe.encrypt(forge.util.encodeUtf8(data), 'RSA-OAEP', {
            md: forge.md.sha256.create(),
            mgf1: {
                md: forge.md.sha1.create()
            }
        });
    
   const encryptedData = forge.util.encode64(encryptedBytes);
    
   console.log("Encrypted data ==> " + encryptedData)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.