【问题标题】:How to generate PublicKey for PrivateKey in X25519?如何在 X25519 中为私钥生成公钥?
【发布时间】:2020-02-23 07:07:35
【问题描述】:

我目前正在使用基于 X25519 密钥的加密。

我的问题是,基本上,如何从现有的 X25519 PrivateKey 派生 PublicKey

我在XDHKeyPairGenerator找到了代码:

BigInteger publicKey = ops.computePublic(privateKey.clone());

但是这个包是特定于平台的,因此无法访问。而且我找不到通过可公开访问的接口执行此操作的方法。

【问题讨论】:

    标签: java cryptography public-key-encryption public-key elliptic-curve


    【解决方案1】:

    到目前为止,我只发现了一种通过 JDK 提供的接口来实现它的方法(不使用任何额外的库,如 Bouncy Castle 或 Google Tink):

    public class StaticSecureRandom extends SecureRandom {
    
        private final byte[] privateKey;
    
        public StaticSecureRandom(byte[] privateKey) {
            this.privateKey = privateKey.clone();
        }
    
        @Override
        public void nextBytes(byte[] bytes) {
            System.arraycopy(privateKey, 0, bytes, 0, privateKey.length);
        }
    
    }
    
        public PublicKey generatePublicKeyFromPrivate(PrivateKey privateKey) throws GeneralSecurityException {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(X25519);
            keyPairGenerator.initialize(new NamedParameterSpec(X25519), new StaticSecureRandom(getScalar(privateKey)));
            return keyPairGenerator.generateKeyPair().getPublic();
        }
    

    这不是一个非常优雅的解决方案,但它可以在没有任何第三方库的情况下工作,我找不到任何其他方式。

    【讨论】:

      【解决方案2】:

      您必须标量乘以 私钥(这只是一个大数字)25519 曲线生成点

      这里有一些python代码来说明:

      from tinyec import registry
      import secrets
      
      curve = registry.get_curve('curve25519')
      
      def compress_point(point):
          return hex(point.x) + hex(point.y % 2)[2:]
      
      
      privKey = secrets.randbelow(curve.field.n)
      pubKey = privKey * curve.g //the key step for you...
      
      
      print("private key:", hex(privKey))
      print("public key:", compress_point(pubKey))
      

      如果您让我知道 Java 库,我会尽力提供进一步帮助。

      【讨论】:

      • 看起来像纯 Java 11+,没有额外的库。
      • 我收到了raise ValueError("Unknown elliptic curve name")
      • @Markkkkk 是的,那只是因为它无法识别您指定的曲线
      • @Woodstock,我注意到了。我想知道 tinyec 注册表中 25519 的正确椭圆曲线名称是什么?我一直在寻找有关此的 python 解决方案。还是没有运气。
      【解决方案3】:

      BouncyCastle 有 Ed25519KeyPairGenerator、X25519KeyPairGenerator、PrivateKeyInfoFactory 和 SubjectPublicKeyInfoFactory 可以协助制作密钥。这是 C# 中的一个示例。用 X25519KeyPairGenerator 替换 ECKeyPairGenerator。此示例使用标准键和 NIST 曲线,因为我无法让 Curve25519 使用 X25519 生成的键,因为当前实现不支持 oid。

      public static async Task Bouncy()
          {
              var originalSecret = "X25519 example";
              var message = Encoding.UTF8.GetBytes(originalSecret);
      
              // Generate signing keys
              var gen = new Ed25519KeyPairGenerator();
              gen.Init(new Ed25519KeyGenerationParameters(new SecureRandom()));
              var kp = gen.GenerateKeyPair();
      
              // Sign data with private key
              var signer = new Ed25519Signer();
              signer.Init(true, kp.Private);
              signer.BlockUpdate(message, 0, message.Length);
              var sig = signer.GenerateSignature();
      
              // Verify signature with public key
              var verifier = new Ed25519Signer();
              verifier.Init(false, kp.Public);
              verifier.BlockUpdate(message, 0, message.Length);
              var sigresult = verifier.VerifySignature(sig);
      
              // Generate encryption keys
              var genX = new ECKeyPairGenerator();
              genX.Init(new KeyGenerationParameters(new SecureRandom(), 521));
      
              var p1 = genX.GenerateKeyPair();
              var p1_private = ECPrivateKeyStructure.GetInstance(PrivateKeyInfoFactory.CreatePrivateKeyInfo(p1.Private));
              var p1_x25519_priv = new X25519PrivateKeyParameters(p1_private.GetDerEncoded(), 0);
      
              var p2 = genX.GenerateKeyPair();
              var p2_public = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(p2.Public);
              var p2_x25519_pub = new X25519PublicKeyParameters(p2_public.GetDerEncoded(), 0);
      
              // Generate secret from keys
              var secret = new byte[32];
              p1_x25519_priv.GenerateSecret(p2_x25519_pub, secret, 0);
      
              // Setup ECIES (Elliptical Curve Integrated Encryption Scheme)
              var gcm = new GcmBlockCipher(new AesEngine());
              var ies = new IesEngine(new ECDHBasicAgreement(), new Kdf2BytesGenerator(new Sha512Digest()),
                  new HMac(new Sha512Digest()), new PaddedBufferedBlockCipher(gcm.GetUnderlyingCipher()));
      
              // 256bit MAC, 256 key
              var p = new IesWithCipherParameters(secret, new byte[1], 256, 256);
      
              // Encrypt secret
              ies.Init(true, p1.Private, p2.Public, p);
              var encrypted = ies.ProcessBlock(message, 0, message.Length);
      
              // Decrypt secret
              ies.Init(false, p2.Private, p1.Public, p);
              var decrypted = ies.ProcessBlock(encrypted, 0, encrypted.Length);
              var decrypted_string = Encoding.UTF8.GetString(decrypted);
          }
      

      【讨论】:

        猜你喜欢
        • 2019-08-15
        • 2021-07-18
        • 2022-01-13
        • 2019-10-12
        • 1970-01-01
        • 1970-01-01
        • 2014-08-16
        • 2021-08-16
        • 1970-01-01
        相关资源
        最近更新 更多