Как сгенерировать луковый адрес службы tor из открытого ключа в java?

Я пытаюсь сгенерировать луковый адрес, созданный из открытого ключа.

Если следующая строка добавлена ​​в код в предыдущее сообщение, сразу после privateKeyEncoded

String publicKeyEncoded = encoder.encodeToString(publicKey.getEncoded());

Когда я помещаю privateKeyEncoded в /var/lib/tor/hidden_service/private_key, сохраняю publicKeyEncoded и запускаю службу tor, новый Луковый адрес создан. Я пытаюсь получить тот же луковый адрес, что и служба tor, и адрес, созданный из publicKeyEncoded. Используя этот код

import org.apache.commons.codec.binary.Base32;
import org.apache.commons.codec.binary.Base64;

//base64 string from the public key created
String publicKeyTest = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCMnFkJTMZ2ZxnqLwCiB/EWHjsHbnC+sKEIrGbyOTYiTl3LygsekAX6LhgcllscLUFqSKlMRB3jRB0GAPrIc73E/hTnmWBtF8NT8DhZzl06LZ1BtNjfON1pHm87STMAayiSaXPmSOwIqOA89aJPcA9m4v4IhtjYSFXmCAsE4RqoAwIDAQAB";
//the onion address the tor service gives when the private key is used
String onionAddressTest = "qqkhrc4men3fiqyl";

byte[] publicKeyDecoded = Base64.decodeBase64(publicKeyTest);
MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
byte[] sha1hash = messageDigest.digest(publicKeyDecoded);
int numberOfCharacters = 10;
byte[] reducedHash = new byte[numberOfCharacters];
for(int i = 0; i < numberOfCharacters; i++) {
    reducedHash[i] = sha1hash[i];
}
Base32 base32encoder = new Base32();
String onionAddress = base32encoder.encodeAsString(reducedHash).toLowerCase();
System.out.println(onionAddress);  // but this gives "7j3iz4of464hje2e"

Я попытался использовать spongycastle, чтобы воспроизвести мое преобразование, но получил тот же ответ. Это заставляет меня думать, что что-то не так с тем, как я генерирую открытый ключ, или что-то не так с моим первоначальным преобразованием из base64.

Учитывая открытый ключ (publicKeyTest), как вы можете получить луковый адрес (onionAddressTest) с помощью java?


person user728785    schedule 14.04.2018    source источник


Ответы (1)


Согласно этому и это вам нужно хешировать только часть, начинающуюся со смещения 22 X Кодировка .509 SubjectPublicKeyInfo, используемая Java, которая называет ее «X.509», и OpenSSL, которая называет ее «PUBKEY». Я не могу найти какой-либо фактический документ Tor по этому вопросу, но я не верю, что это может быть случайным, что это именно начало зависимых от алгоритма данных в формате SPKI для ключа RSA-1024:

$ openssl asn1parse -i <49833260.b64
    0:d=0  hl=3 l= 159 cons: SEQUENCE
    3:d=1  hl=2 l=  13 cons:  SEQUENCE
    5:d=2  hl=2 l=   9 prim:   OBJECT            :rsaEncryption
   16:d=2  hl=2 l=   0 prim:   NULL
   18:d=1  hl=3 l= 141 prim:  BIT STRING
# 18 +3 for DER tag+len +1 for unusedbitcount in BITSTRING = 22
# and the content beginning at 22 is:
$ openssl asn1parse -i -strparse 22 <49833260.b64
    0:d=0  hl=3 l= 137 cons: SEQUENCE
    3:d=1  hl=3 l= 129 prim:  INTEGER           :8C9C59094CC6766719EA2F00A207F11
61E3B076E70BEB0A108AC66F23936224E5DCBCA0B1E9005FA2E181C965B1C2D416A48A94C441DE34
41D0600FAC873BDC4FE14E799606D17C353F03859CE5D3A2D9D41B4D8DF38DD691E6F3B4933006B2
8926973E648EC08A8E03CF5A24F700F66E2FE0886D8D84855E6080B04E11AA803
  135:d=1  hl=2 l=   3 prim:  INTEGER           :010001
# which is (exactly) the RSAPublicKey structure from PKCS1

Таким образом, чтобы сделать это на Java, вы можете просто предположить RSA-1024 или с помощью BouncyCastle (и я предполагаю, но не проверял, spongycastle), вы действительно можете правильно проанализировать ASN.1:

byte[] pubkeyder = Base64.decode("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCMnFkJTMZ2ZxnqLwCiB/EWHjsHbnC+sKEIrGbyOTYiTl3LygsekAX6LhgcllscLUFqSKlMRB3jRB0GAPrIc73E/hTnmWBtF8NT8DhZzl06LZ1BtNjfON1pHm87STMAayiSaXPmSOwIqOA89aJPcA9m4v4IhtjYSFXmCAsE4RqoAwIDAQAB");
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
// method 1
byte[] x1 = sha1.digest (Arrays.copyOfRange(pubkeyder, 22, pubkeyder.length));
System.out.println (new String(b32enc(Arrays.copyOf(x1,10))).toLowerCase());
// method 2
byte[] x2 = sha1.digest (SubjectPublicKeyInfo.getInstance(pubkeyder).getPublicKeyData().getOctets());
System.out.println (new String(b32enc(Arrays.copyOf(x2,10))).toLowerCase());
-> 
qqkhrc4men3fiqyl
qqkhrc4men3fiqyl
person dave_thompson_085    schedule 14.04.2018
comment
Спасибо. Точно. - person user728785; 15.04.2018