Java 密钥库中的 Lazysodium 密钥
Lazysodium keys in Java Keystore
我正在使用 Lazysodium 库 (https://terl.gitbook.io/lazysodium/) 从 Java 访问 libsodium,专门用于 Ed25519 数字签名。
我还希望能够将密钥对存储在标准 Java 密钥库中。但是,libsodium 使用字节数组而不是 JCA Keypair 实例,因此不清楚如何实现这一点。
特别是,您如何:
- 将用于 Libsodium 的字节数组 Ed25519 密钥转换为 JCA 密钥对?
- 将 JCA 密钥对转换回适用于 libsodium 的字节数组?
原始私钥 Ed25519 和 java.security.PrivateKey
之间的转换是可能的,例如使用 BouncyCastle 如下:
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.KeyFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.edec.EdECObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.util.encoders.Hex;
...
// Generate private test key
PrivateKey privateKey = loadPrivateKey("Ed25519");
byte[] privateKeyBytes = privateKey.getEncoded();
System.out.println(Base64.getEncoder().encodeToString(privateKeyBytes)); // PKCS#8-key, check this in an ASN.1 Parser, e.g. https://lapo.it/asn1js/
// java.security.PrivateKey to raw Ed25519 key
Ed25519PrivateKeyParameters ed25519PrivateKeyParameters = (Ed25519PrivateKeyParameters)PrivateKeyFactory.createKey(privateKeyBytes);
byte[] rawKey = ed25519PrivateKeyParameters.getEncoded();
System.out.println(Hex.toHexString(rawKey)); // equals the raw 32 bytes key from the PKCS#8 key
// Raw Ed25519 key to java.security.PrivateKey
KeyFactory keyFactory = KeyFactory.getInstance("Ed25519");
PrivateKeyInfo privateKeyInfo = new PrivateKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519), new DEROctetString(rawKey));
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyInfo.getEncoded());
PrivateKey privateKeyReloaded = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
byte[] privateKeyBytesReloaded = privateKeyReloaded.getEncoded();
System.out.println(Base64.getEncoder().encodeToString(privateKeyBytesReloaded)); // equals the PKCS#8 key from above
私钥生成的位置:
private static PrivateKey loadPrivateKey(String algorithm) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair.getPrivate();
}
对于 X25519 类似,将所有 Ed25519
替换为 X25519
。
原始 public X25519 密钥和 java.security.PublicKey
之间的转换(反之亦然)可以在 中找到。对于原始 public Ed25519 密钥,过程是类似的,其中每个 X25519
必须替换为 Ed25519
。
不过,我没有测试过密钥库中是否可以存储Ed25519或X25519密钥。
我正在使用 Lazysodium 库 (https://terl.gitbook.io/lazysodium/) 从 Java 访问 libsodium,专门用于 Ed25519 数字签名。
我还希望能够将密钥对存储在标准 Java 密钥库中。但是,libsodium 使用字节数组而不是 JCA Keypair 实例,因此不清楚如何实现这一点。
特别是,您如何:
- 将用于 Libsodium 的字节数组 Ed25519 密钥转换为 JCA 密钥对?
- 将 JCA 密钥对转换回适用于 libsodium 的字节数组?
原始私钥 Ed25519 和 java.security.PrivateKey
之间的转换是可能的,例如使用 BouncyCastle 如下:
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.KeyFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.edec.EdECObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.util.encoders.Hex;
...
// Generate private test key
PrivateKey privateKey = loadPrivateKey("Ed25519");
byte[] privateKeyBytes = privateKey.getEncoded();
System.out.println(Base64.getEncoder().encodeToString(privateKeyBytes)); // PKCS#8-key, check this in an ASN.1 Parser, e.g. https://lapo.it/asn1js/
// java.security.PrivateKey to raw Ed25519 key
Ed25519PrivateKeyParameters ed25519PrivateKeyParameters = (Ed25519PrivateKeyParameters)PrivateKeyFactory.createKey(privateKeyBytes);
byte[] rawKey = ed25519PrivateKeyParameters.getEncoded();
System.out.println(Hex.toHexString(rawKey)); // equals the raw 32 bytes key from the PKCS#8 key
// Raw Ed25519 key to java.security.PrivateKey
KeyFactory keyFactory = KeyFactory.getInstance("Ed25519");
PrivateKeyInfo privateKeyInfo = new PrivateKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519), new DEROctetString(rawKey));
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyInfo.getEncoded());
PrivateKey privateKeyReloaded = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
byte[] privateKeyBytesReloaded = privateKeyReloaded.getEncoded();
System.out.println(Base64.getEncoder().encodeToString(privateKeyBytesReloaded)); // equals the PKCS#8 key from above
私钥生成的位置:
private static PrivateKey loadPrivateKey(String algorithm) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair.getPrivate();
}
对于 X25519 类似,将所有 Ed25519
替换为 X25519
。
原始 public X25519 密钥和 java.security.PublicKey
之间的转换(反之亦然)可以在 X25519
必须替换为 Ed25519
。
不过,我没有测试过密钥库中是否可以存储Ed25519或X25519密钥。