在 Java 中导入 ANSI X9.63 格式的密钥对

Importing ANSI X9.63 formatted key pair in Java

我已经在 iOS 上生成了一个密钥对,并使用以下代码创建了一个数据表示:

var publicKey, privateKey: SecKey?
let keyattribute = [
    kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
    kSecAttrKeySizeInBits as String : 256
    ] as CFDictionary
SecKeyGeneratePair(keyattribute, &publicKey, &privateKey)

var error: Unmanaged<CFError>?
let pubkeyRep = SecKeyCopyExternalRepresentation(publicKey!, &error) as Data?
let prikeyRep = SecKeyCopyExternalRepresentation(privateKey!, &error) as Data?

根据 Apple 的文档,SecKeyCopyExternalRepresentation function encodes these keys using uncompressed ANSI X9.63 format

我想将这些字节数组转换为 Java 中的 PublicKeyPrivateKey 对象。

我发现的一些示例 (using SunJCE) and (使用 BouncyCastle)适用于 public 密钥,但它们没有描述导入私钥的方法。

请注意 Apple 文档中的前 65 个字节是如何将未压缩的 public 密钥 (04 || X || Y) 与私有标量 (|| K) 连接在一起的。去掉这些字节,你就可以创建私钥了。我希望这对某人有所帮助。

/*
 *  For an elliptic curve private key, the output is formatted as the public key
 * concatenated with the big endian encoding of the secret scalar, or 04 || X || Y || K.
 */
private PrivateKey createECPrivateKey(byte[] rawBytes) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidParameterSpecException {
    KeyFactory kf = KeyFactory.getInstance("EC");
    BigInteger s = new BigInteger(Arrays.copyOfRange(rawBytes, 65, rawBytes.length));
    return kf.generatePrivate(new ECPrivateKeySpec(s, ecParameterSpecForCurve("secp256r1")));
}