如何从 java 中的 public 键生成 tor 服务洋葱地址?
How to generate a tor service onion address from the public key in java?
我正在尝试生成从 public 密钥生成的洋葱地址。
如果在中的代码中添加以下行,就在privateKeyEncoded
之后
String publicKeyEncoded = encoder.encodeToString(publicKey.getEncoded());
当我将 privateKeyEncoded 放入 /var/lib/tor/hidden_service/private_key 时,保存 public KeyEncoded 并启动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 来复制我的转换,但得到了相同的答案。这让我觉得我生成 public 密钥的方式有问题,或者我从 base64.
的初始转换有问题
给定 public 密钥 (publicKeyTest) 你如何获得洋葱地址 (onionAddressTest ) 使用 java?
根据 this and this,您只需要 散列从 Java 使用的 X.509 SubjectPublicKeyInfo 编码的偏移量 22 开始的部分,调用它'X.509' 并由 OpenSSL 调用它 'PUBKEY'。我找不到关于此的任何实际 Tor 文档,但我不认为这恰好是 RSA-1024 密钥的 SPKI 格式的算法相关数据的开始:
$ 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
我正在尝试生成从 public 密钥生成的洋葱地址。
如果在
String publicKeyEncoded = encoder.encodeToString(publicKey.getEncoded());
当我将 privateKeyEncoded 放入 /var/lib/tor/hidden_service/private_key 时,保存 public KeyEncoded 并启动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 来复制我的转换,但得到了相同的答案。这让我觉得我生成 public 密钥的方式有问题,或者我从 base64.
的初始转换有问题给定 public 密钥 (publicKeyTest) 你如何获得洋葱地址 (onionAddressTest ) 使用 java?
根据 this and this,您只需要 散列从 Java 使用的 X.509 SubjectPublicKeyInfo 编码的偏移量 22 开始的部分,调用它'X.509' 并由 OpenSSL 调用它 'PUBKEY'。我找不到关于此的任何实际 Tor 文档,但我不认为这恰好是 RSA-1024 密钥的 SPKI 格式的算法相关数据的开始:
$ 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