【问题标题】:String to PublicKey using Diffie-Hellman algorithm使用 Diffie-Hellman 算法将字符串转换为 PublicKey
【发布时间】:2014-05-05 18:39:30
【问题描述】:

我有一个由我的客户提供的公钥字符串(128 字节字节到十六进制处理)。我需要使用客户端提供的私钥和公钥生成共享密钥。将字符串转换为公钥时出现异常。我尝试解码/编码字节,没有改善。我有以下代码。

// 这是一个示例密钥。

private static final String PUB_KEY = "0DC1B7102DE3F6785A284ABFCA1822A6B59C947B5F2FAAE" + "672D8EE29C3D801BC153777CD3AF5478FD25C234C50BBABF8CD5215A8F1CB19B0B4A24FD5E9" + "412264646E2A06FCB5929FFBE196A1BD58B9927424C3B3D0388FDDA15FD1FF1C3E7600A629E" + 
"B3F0B38B85CCCE03D44CF8D53B2E4E5EFD54E991CE92E55B10FCCD79F04";

public static void main(String[] argv) throws Exception {   
    PublicKey key = getKey(h2b(PUB_KEY));
}

private static PublicKey getKey(final byte[] pubKey) throws Exception {
    final KeyFactory keyFactory = KeyFactory.getInstance("DH");  
    final X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubKey);
    return keyFactory.generatePublic(keySpec); // THROWS EXCEPTION
}

private static byte[] h2b(String hex) {
    if ((hex.length() & 0x01) == 0x01)
        throw new IllegalArgumentException();
    byte[] bytes = new byte[hex.length() / 2];
    for (int idx = 0; idx < bytes.length; ++idx) {
        int hi = Character.digit((int) hex.charAt(idx * 2), 16);
        int lo = Character.digit((int) hex.charAt(idx * 2 + 1), 16);
        if ((hi < 0) || (lo < 0))
            throw new IllegalArgumentException();
        bytes[idx] = (byte) ((hi << 4) | lo);
    }
    return bytes;
}

抛出以下异常。有什么帮助解决这个问题吗?

线程“main”中的异常 java.security.spec.InvalidKeySpecException:不适当的密钥规范 在 com.sun.crypto.provider.DHKeyFactory.engineGeneratePublic(DHKeyFactory.java:87)

【问题讨论】:

  • 16 进制数怎么可能是负数?

标签: java encryption public-key-encryption diffie-hellman


【解决方案1】:

X509EncodedKeySpec 应包含具有 ASN.1 SubjectPublicKeyInfo 结构的字节数组。

您示例中的 PUB_KEY 可能是原始键值(y 中的 javax.crypto.spec.DHPublicKeySpec)不足以创建密钥规范。

您应该向您的客户对方询问 ASN.1 表单中的正确公钥,以用作X509EncodedKeySpec(这是最好的)或pg 所需的DHPublicKeySpec 参数的输入。

【讨论】:

  • 感谢您的回复。我有从 pem 生成的 p 和 g 值。我也生成了我的密钥对。客户的代码在 C 中。我已邮寄客户以获取 ASN.1 形式的公钥。我可以用我生成的 p、g 和密钥对做些什么吗?
【解决方案2】:
  1. 按照 3 步将 String 转换为 DH、DSA 公钥或私钥

生成公钥

KeyPair pair = keyPair.generateDHKeyPair();// this will generate public private key
PublicKey publicKey=pair.getPublic();

2:将publickey转换为publicKey.getEncoded返回byte[]。

byte[] byte_pubkey = public_key.getEncoded();
System.out.println("\nBYTE KEY::: " + byte_pubkey);

3://将字节转换为字符串

String pukkey64 = "";
        //byte[] pukkey64 = new byte[0];
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            Base64.Encoder encoder = Base64.getEncoder();
            pukkey64 = encoder.encodeToString(byte_pubkey);
            Log.e("pukkey64", new String(pukkey64));
        } 

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // GenpubKeyFromString(pair2.getPublic().toString());
            try {
                GenpubKeyFromString(pukkey64);
            } catch (GeneralSecurityException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }

这个函数生成你需要的公钥或私钥

@RequiresApi(api = Build.VERSION_CODES.O)
    void GenpubKeyFromString(String pubKey) throws GeneralSecurityException, UnsupportedEncodingException {
        Base64.Decoder decoder = Base64.getDecoder();
        byte[] publicKeyBytes=decoder.decode(pubKey);
        KeyFactory kf = KeyFactory.getInstance("DH");
        PublicKey publicKey = kf.generatePublic(new X509EncodedKeySpec(publicKeyBytes));
        Log.e("publicKey String", publicKey.toString());
        
    }

// 将字符串转换为私钥

public static PrivateKey GetPrivateKeyFromString(String priKey) throws GeneralSecurityException, UnsupportedEncodingException {
        byte[] decodedKey = Base64.decode(priKey, Base64.NO_WRAP);
        KeyFactory kf = KeyFactory.getInstance("DH");
        PrivateKey privateKey = kf.generatePrivate(new PKCS8EncodedKeySpec(decodedKey));
        return privateKey;
    }

【讨论】:

    猜你喜欢
    • 2020-12-01
    • 2018-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多