You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Java生成Tor洋葱服务的有效RSA 1024私钥并获取.onion地址

嘿,我来帮你搞定用Java生成有效Tor洋葱服务私钥的问题!你现在尝试的RSA 1024位密钥其实对应Tor v2洋葱服务的规范,但目前Tor已经逐步淘汰v2了,我会同时给你v2兼容版和当前推荐的v3标准版的实现方案。

首先先明确核心要点:

  • Tor v2洋葱服务:依赖1024位RSA密钥,私钥需为PKCS#1格式(Java默认生成的是PKCS#8,需要转换),.onion地址由公钥的SHA-1哈希前8字节做Base32编码得到
  • Tor v3洋葱服务:使用ED25519密钥(当前安全标准),.onion地址由公钥的Blake2b-256哈希前32字节做Base32编码得到

方案1:生成Tor v2洋葱服务密钥(兼容旧版本)

你之前的代码已经生成了RSA密钥,但没转换成Tor需要的PKCS#1格式,这里用BouncyCastle工具类来处理格式转换(Java标准库没有直接的PKCS#1转换工具):

首先引入BouncyCastle依赖(Maven为例):

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.70</version>
</dependency>

完整实现代码:

import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1SequenceGenerator;
import org.bouncycastle.asn1.ASN1BitString;
import org.bouncycastle.asn1.ASN1InputStream;

import java.security.*;
import java.security.spec.RSAPrivateKeySpec;
import java.util.Base64;
import java.io.ByteArrayOutputStream;

public class TorV2KeyGenerator {
    public static void main(String[] args) throws Exception {
        // 生成符合Tor v2要求的1024位RSA密钥对
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(1024, new SecureRandom());
        KeyPair keyPair = keyGen.generateKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();
        
        // 将Java默认的PKCS#8私钥转换为Tor需要的PKCS#1格式
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        RSAPrivateKeySpec rsaPrivateSpec = keyFactory.getKeySpec(privateKey, RSAPrivateKeySpec.class);
        byte[] pkcs1PrivateBytes = buildPKCS1PrivateKey(rsaPrivateSpec);
        
        // 输出Base64编码的私钥(可直接填入Tor配置的HiddenServicePrivateKey字段)
        String base64PrivateKey = Base64.getEncoder().encodeToString(pkcs1PrivateBytes);
        System.out.println("Tor v2私钥(Base64): " + base64PrivateKey);
        
        // 生成对应的.onion地址
        byte[] rsaPublicKeyBytes = extractRSAPublicKeyFromX509(publicKey.getEncoded());
        MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
        byte[] hash = sha1.digest(rsaPublicKeyBytes);
        byte[] onionPrefix = new byte[8];
        System.arraycopy(hash, 0, onionPrefix, 0, 8);
        // 适配Tor的Base32规则:全小写、无填充符
        String onionAddress = Base32.encode(onionPrefix).toLowerCase().replaceAll("=", "") + ".onion";
        System.out.println("Tor v2洋葱地址: " + onionAddress);
    }
    
    // 手动构造PKCS#1格式的RSA私钥DER编码
    private static byte[] buildPKCS1PrivateKey(RSAPrivateKeySpec spec) throws Exception {
        ASN1SequenceGenerator seqGen = new ASN1SequenceGenerator(new ByteArrayOutputStream());
        seqGen.addObject(new ASN1Integer(0)); // 版本号
        seqGen.addObject(new ASN1Integer(spec.getModulus()));
        seqGen.addObject(new ASN1Integer(spec.getPublicExponent()));
        seqGen.addObject(new ASN1Integer(spec.getPrivateExponent()));
        seqGen.addObject(new ASN1Integer(spec.getPrimeP()));
        seqGen.addObject(new ASN1Integer(spec.getPrimeQ()));
        seqGen.addObject(new ASN1Integer(spec.getExponentP()));
        seqGen.addObject(new ASN1Integer(spec.getExponentQ()));
        seqGen.addObject(new ASN1Integer(spec.getCrtCoefficient()));
        return seqGen.getOutputStream().toByteArray();
    }
    
    // 从X.509格式的公钥中提取原始RSA公钥部分
    private static byte[] extractRSAPublicKeyFromX509(byte[] x509Bytes) throws Exception {
        try (ASN1InputStream asn1In = new ASN1InputStream(x509Bytes)) {
            ASN1Sequence seq = (ASN1Sequence) asn1In.readObject();
            ASN1BitString publicKeyBitString = (ASN1BitString) seq.getObjectAt(1);
            return publicKeyBitString.getBytes();
        }
    }
}

方案2:生成Tor v3洋葱服务密钥(当前推荐)

Tor v3是官方主推的安全标准,依赖ED25519密钥,同样需要BouncyCastle支持:

import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.generators.Ed25519KeyPairGenerator;
import org.bouncycastle.crypto.params.Ed25519KeyGenerationParameters;
import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters;
import org.bouncycastle.crypto.digests.Blake2bDigest;
import org.bouncycastle.util.encoders.Base32;

import java.security.SecureRandom;
import java.util.Base64;

public class TorV3KeyGenerator {
    public static void main(String[] args) {
        // 生成ED25519密钥对
        Ed25519KeyPairGenerator keyGen = new Ed25519KeyPairGenerator();
        keyGen.init(new Ed25519KeyGenerationParameters(new SecureRandom()));
        AsymmetricCipherKeyPair keyPair = keyGen.generateKeyPair();
        
        Ed25519PrivateKeyParameters privateKeyParams = (Ed25519PrivateKeyParameters) keyPair.getPrivate();
        Ed25519PublicKeyParameters publicKeyParams = (Ed25519PublicKeyParameters) keyPair.getPublic();
        
        // 生成Tor v3洋葱地址:公钥做Blake2b-256哈希,取前32字节Base32编码
        byte[] publicKeyBytes = publicKeyParams.getEncoded();
        Blake2bDigest blake2b = new Blake2bDigest(256);
        blake2b.update(publicKeyBytes, 0, publicKeyBytes.length);
        byte[] hash = new byte[blake2b.getDigestSize()];
        blake2b.doFinal(hash, 0);
        
        String onionAddress = Base32.encode(hash).toLowerCase().replaceAll("=", "") + ".onion";
        System.out.println("Tor v3洋葱地址: " + onionAddress);
        
        // 输出PKCS#8格式的PEM私钥(可直接用于Tor配置)
        byte[] privateKeyBytes = privateKeyParams.getEncoded();
        String pemPrivateKey = "-----BEGIN PRIVATE KEY-----\n" +
                Base64.getEncoder().encodeToString(privateKeyBytes) +
                "\n-----END PRIVATE KEY-----";
        System.out.println("Tor v3私钥(PEM格式):\n" + pemPrivateKey);
    }
}

关键注意事项

  1. 依赖BouncyCastle:Java标准库对ASN.1格式处理和ED25519原生支持有限,必须引入第三方库完成格式转换
  2. Base32编码适配:Tor使用无填充、全小写的Base32编码,需要手动去掉编码后的=填充符
  3. 版本选择:Tor v2已被官方弃用,大部分公共Tor节点不再支持,优先选择v3方案

内容的提问来源于stack exchange,提问作者user728785

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:05:15