43

I am trying to encode a message with SH1 RSA but I have no experience with security subject except some base information about RSA. I have been given a private key as String. I have managed to write following code block to do the job but I am not sure if I am doing the job securely and correctly.

I am not an expert but putting my private key as String in code is not secure I guess. Can anyone guide me?

String privateKeyString = "mykeyhere...";
byte[] privateKeyBytes = privateKeyString.getBytes();
String encodedPrivateKey = Base64.encodeToString(privateKeyBytes, Base64.URL_SAFE);

KeyFactory factory = KeyFactory.getInstance(RSA);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedPrivateKey.getBytes());
RSAPrivateKey privateKey = (RSAPrivateKey) factory.generatePrivate(keySpec);

Signature instance = Signature.getInstance(ALGORITHM);
instance.initSign(privateKey);
instance.update(content.getBytes());
return new String(instance.sign());

My private key is in form as:

"-----BEGIN PRIVATE KEY-----\n"+
"MIIE...\n"+
"cH0iRj...\n"+
"O0Hhj...\n"+
.
.
.
"fG6...\n"+
"B6/hF...\n"+
"3Mq38...\n"+
"-----END PRIVATE KEY-----\n"
computingfreak
  • 4,939
  • 1
  • 34
  • 51
Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112

1 Answers1

55

Your key format is an unencrypted base64-encoded PKCS8-encoded private key. Here is an example of how to decode it into a private key. (Don't worry about the security of the private key in this example, it is just a throwaway for the example).

import java.io.*;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import android.util.Base64;

public class ReadPKCS8Pem {

    private final static String PRIVATE_KEY = 
            "-----BEGIN PRIVATE KEY-----\n"
            + "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAM7t8Ub1DP+B91NJ\n"
            + "nC45zqIvd1QXkQ5Ac1EJl8mUglWFzUyFbhjSuF4mEjrcecwERfRummASbLoyeMXl\n"
            + "eiPg7jvSaz2szpuV+afoUo9c1T+ORNUzq31NvM7IW6+4KhtttwbMq4wbbPpBfVXA\n"
            + "IAhvnLnCp/VyY/npkkjAid4c7RoVAgMBAAECgYBcCuy6kj+g20+G5YQp756g95oN\n"
            + "dpoYC8T/c9PnXz6GCgkik2tAcWJ+xlJviihG/lObgSL7vtZMEC02YXdtxBxTBNmd\n"
            + "upkruOkL0ElIu4S8CUwD6It8oNnHFGcIhwXUbdpSCr1cx62A0jDcMVgneQ8vv6vB\n"
            + "/YKlj2dD2SBq3aaCYQJBAOvc5NDyfrdMYYTY+jJBaj82JLtQ/6K1vFIwdxM0siRF\n"
            + "UYqSRA7G8A4ga+GobTewgeN6URFwWKvWY8EGb3HTwFkCQQDgmKtjjJlX3BotgnGD\n"
            + "gdxVgvfYG39BL2GnotSwUbjjce/yZBtrbcClfqrrOWWw7lPcX1d0v8o3hJfLF5dT\n"
            + "6NAdAkA8qAQYUCSSUwxJM9u0DOqb8vqjSYNUftQ9dsVIpSai+UitEEx8WGDn4SKd\n"
            + "V8kupy/gJlau22uSVYI148fJSCGRAkBz+GEHFiJX657YwPI8JWHQBcBUJl6fGggi\n"
            + "t0F7ibceOkbbsjU2U4WV7sHyk8Cei3Fh6RkPf7i60gxPIe9RtHVBAkAnPQD+BmND\n"
            + "By8q5f0Kwtxgo2+YkxGDP5bxDV6P1vd2C7U5/XxaN53Kc0G8zu9UlcwhZcQ5BljH\n"
            + "N24cUWZOo+60\n"
            + "-----END PRIVATE KEY-----";
    
    public static void main(String[] args) throws Exception {
        // Read in the key into a String
        StringBuilder pkcs8Lines = new StringBuilder();
        BufferedReader rdr = new BufferedReader(new StringReader(PRIVATE_KEY));
        String line;
        while ((line = rdr.readLine()) != null) {
            pkcs8Lines.append(line);
        }
        
        // Remove the "BEGIN" and "END" lines, as well as any whitespace
        
        String pkcs8Pem = pkcs8Lines.toString();
        pkcs8Pem = pkcs8Pem.replace("-----BEGIN PRIVATE KEY-----", "");
        pkcs8Pem = pkcs8Pem.replace("-----END PRIVATE KEY-----", "");
        pkcs8Pem = pkcs8Pem.replaceAll("\\s+","");
        
        // Base64 decode the result
        
        byte [] pkcs8EncodedBytes = Base64.decode(pkcs8Pem, Base64.DEFAULT);
        
        // extract the private key
        
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8EncodedBytes);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        PrivateKey privKey = kf.generatePrivate(keySpec);
        System.out.println(privKey);
    }

}
jumping_monkey
  • 5,941
  • 2
  • 43
  • 58
President James K. Polk
  • 40,516
  • 21
  • 95
  • 125
  • if i print this: Log.i("","Reversed PEM:" + Base64.encodeToString(privkey.getEncoded(),Base64.Default)); Shouldn't it print the original pem string. In my case its not same.. – Farhan May 16 '17 at 11:43
  • 3
    @Farhan: No, not necessarily. The implementation may for example swap the positions of p and q in the encoded form, which will result in different (but equivalent) output. – President James K. Polk May 16 '17 at 12:35
  • ok thanx alot, really appreciated. could you pass a comment on following please. my ca key is 4096 and my cert key is 2048 rsa. sometimes, during ssl handshake, it stucks/hangs. i was wondering its because of some dns resolve thing. will key length have an effect on that? I've already asked a question here: http://stackoverflow.com/questions/43863646/ssl-handshake-hang – Farhan May 17 '17 at 06:03
  • getting error: java.lang.RuntimeException: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag Generated key using : https://gist.github.com/ygotthilf/baa58da5c3dd1f69fae9 – Bikesh M Jan 30 '18 at 14:13
  • I found the mistake I was making, thanks @JamesKPolk. Your answer was really helpful. – Rito Oct 12 '18 at 12:08
  • 16
    If anyone is using `java.util.Base64` instead of `android.util.Base64` then the `decode` line changes to ```byte [] pkcs8EncodedBytes = Base64.getDecoder().decode(pkcs8Pem)``` – KJ50 Apr 05 '21 at 22:52
  • 1
    @Rito do you still remember your mistake, as I now have the same. – Jdruwe May 18 '21 at 10:20