1

I'm trying to generate a valid private key for a tor onion service in java. With this private key I want to get a valid .onion address.

I have run various combinations (with this bit/without that bit) of the code below

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKeyGenerated = keyPair.getPrivate();

KeyFactory keyFactory =  KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyGenerated.getEncoded()));

Base64.Encoder encoder = Base64.getEncoder();
String privateKeyEncoded = encoder.encodeToString(privateKey.getEncoded());

String fileName = "{{where I'm wanting to store the file}}";    
Writer writer = new FileWriter(fileName);
writer.write("-----BEGIN RSA PRIVATE KEY-----\n");
writer.write(privateKeyEncoded);
writer.write("\n-----END RSA PRIVATE KEY-----\n");
writer.close();

After generation I copy the key to my /var/lib/tor/hidden_service/private_key, remove any associated hostname and start the tor service. In the logs I get the error:

TLS error: wrong tag (in asn1 encoding routines:ASN1_CHECK_TLEN:---)
TLS error: nested asn1 error (in asn1 encoding routines:ANS1_D2I_EX_PRIMITIVE:---) 
TLS error: nested asn1 error (in asn1 endoding routines:ASN1_TEMPLATE_NOEXP_D2I:---) 
TLS error: RSA lib (in rsa routines:OLD_RSA_PRIV_DECODE:---)

If a resulting .onion address is generated it doesn't work.

How do I generate a valid private key?

user728785
  • 532
  • 1
  • 4
  • 18
  • 1
    Try to change `BEGIN RSA PRIVATE KEY` with `BEGIN PRIVATE KEY`. The final tag too – pedrofb Apr 05 '18 at 11:51
  • I'm embarrassed to admit that that worked. Thanks! – user728785 Apr 05 '18 at 12:13
  • Do not worry about that, it's not a trivial issue. Now I'm going to explain it – pedrofb Apr 05 '18 at 12:18
  • Cool, if you post as an answer I can accept your solution. – user728785 Apr 05 '18 at 12:24
  • 1
    FYI: you don't need to encode, run it through a factory, and encode again; the latter two steps are a no-op. Also, the PEM spec requires the base64 data to be broken into lines not more than 64 chars, although MIME changed this to 76 and most sw I know accepts that, and `java.util.Base64.getMimeEncoder` creates it. Tor apparently accepts one enormous line but other sw may not. – dave_thompson_085 Apr 14 '18 at 22:48

1 Answers1

3

Solution: Change BEGIN RSA PRIVATE KEY with BEGIN PRIVATE KEY

Java encodes the key IN PKCS#8 format

PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyGenerated.getEncoded()));

But you are generating a PEM file with the header -----BEGIN RSA PRIVATE KEY----- which is reserved to PKCS#1 keys (old format but very common), and .onion is assuming that it is pkcs1 when it really is pkcs8. See the error

TLS error: RSA lib (in rsa routines:OLD_RSA_PRIV_DECODE:---)

So you need to use the PCKS#8 header -----BEGIN PRIVATE KEY-----

See also this post Load a RSA private key in Java (algid parse error, not a sequence)

pedrofb
  • 37,271
  • 5
  • 94
  • 142