我有一个使用BouncyCastle作为安全提供者的应用程序,但是我想切换到另一个直接使用OpenSSL(consecrypt)的应用程序。我遇到的问题是,我正在使用BouncyCastle提供的密钥生成器中的ECDH“密钥”,但在我的其他库中没有类似的密钥生成器。
为了比较这两者,我将使用两种方法解码这些点,输入如下-
为提高可读性而添加换行符
BADX_GAXp03z_5p05O1-op61KJAl4j9U2sBnAnJ4p_6GSAIyFGU3lM
oC4aIXw_2qlTnplykArgjvwCWw-2g6L44
使用BouncyCastle方法-
public org.bouncycastle.jce.interfaces.ECPublicKey loadECPublicKeyBC(String encodedPublicKey) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException, IOException {
Base64.Decoder base64Decoder = Base64.getUrlDecoder();
byte[] decodedPublicKey = base64Decoder.decode(encodedPublicKey);
KeyFactory keyFactory = KeyFactory.getInstance("ECDH", "BC");
ECParameterSpec ecParameterSpec = ECUtil.getECParameterSpec(openSSLProvider, "prime256v1");
ECPoint ecPoint = ECUtil.decodePoint(decodedPublicKey, ecParameterSpec.getCurve());
ECPublicKeySpec pubSpec = new ECPublicKeySpec(ecPoint, ecParameterSpec);
org.bouncycastle.jce.interfaces.ECPublicKey ecPublicKey = (org.bouncycastle.jce.interfaces.ECPublicKey)keyFactory.generatePublic(pubSpec);
return ecPublicKey;
}
返回的get算法
是EC
。返回的getFormat
是X.509
。
此值的getEncoded
值为-
[48,-126,1,51,48,-127,-20,6,7,42,-122,72,-50,61,2,1,48,
-127,-32,2,1,1,48,44,6,7,42,-122,72,-50,61,1,1,2,33,0,
-1,-1,-1,-1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,48,68,4,32,-1,-1,-1,-1,0,0,0,1,
0,0,0,0,0,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-4,4,32,90,-58,53,-40,-86,58,-109,-25,-77,-21,-67,85,
118,-104,-122,-68,101,29,6,-80,-52,83,-80,-10,59,-50,60,
62,39,-46,96,75,4,65,4,107,23,-47,-14,-31,44,66,71,-8,-68,
-26,-27,99,-92,64,-14,119,3,125,-127,45,-21,51,-96,-12,
-95,57,69,-40,-104,-62,-106,79,-29,66,-30,-2,26,127,-101,
-114,-25,-21,74,124,15,-98,22,43,-50,51,87,107,49,94,-50,
-53,-74,64,104,55,-65,81,-11,2,33,0,-1,-1,-1,-1,0,0,0,0,-1,
-1,-1,-1,-1,-1,-1,-1,-68,-26,-6,-83,-89,23,-98,-124,-13,
-71,-54,-62,-4,99,37,81,2,1,1,3,66,0,4,0,-41,-4,96,23,-89,
77,-13,-1,-102,116,-28,-19,126,-94,-98,-75,40,-112,37,-30,
63,84,-38,-64,103,2,114,120,-89,-2,-122,72,2,50,20,101,55,
-108,-54,2,-31,-94,23,-61,-3,-86,-107,57,-23,-105,41,0,-82,
8,-17,-64,37,-80,-5,104,58,47,-114]
只是使用BouncyCastle EC算法(不是ECDH)我得到 -
[48,-126,1,51,48,-127,-20,6,7,42,-122,72,
-50,61,2,1,48,-127,-32,2,1,1,48,44,6,7,42,
-122,72,-50,61,1,1,2,33,0,-1,-1,-1,-1,0,0,
0,1,0,0,0,0,0,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,48,68,4,32,-1,-1,-1,-1,
0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-4,4,32,90,-58,53,-40,
-86,58,-109,-25,-77,-21,-67,85,118,-104,-122,
-68,101,29,6,-80,-52,83,-80,-10,59,-50,60,62,
39,-46,96,75,4,65,4,107,23,-47,-14,-31,44,66,
71,-8,-68,-26,-27,99,-92,64,-14,119,3,125,
-127,45,-21,51,-96,-12,-95,57,69,-40,-104,-62,
-106,79,-29,66,-30,-2,26,127,-101,-114,-25,
-21,74,124,15,-98,22,43,-50,51,87,107,49,94,
-50,-53,-74,64,104,55,-65,81,-11,2,33,0,-1,-1,
-1,-1,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-68,-26,
-6,-83,-89,23,-98,-124,-13,-71,-54,-62,-4,99,
37,81,2,1,1,3,66,0,4,0,-41,-4,96,23,-89,77,
-13,-1,-102,116,-28,-19,126,-94,-98,-75,40,
-112,37,-30,63,84,-38,-64,103,2,114,120,-89,
-2,-122,72,2,50,20,101,55,-108,-54,2,-31,-94,
23,-61,-3,-86,-107,57,-23,-105,41,0,-82,8,-17,
-64,37,-80,-5,104,58,47,-114]
现在使用concrypt方法-
public ECPublicKey loadECPublicKey(String encodedPublicKey) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException, IOException {
Base64.Decoder base64Decoder = Base64.getUrlDecoder();
byte[] decodedPublicKey = base64Decoder.decode(encodedPublicKey);
KeyFactory keyFactory = KeyFactory.getInstance("EC", "Conscrypt");
ECParameterSpec ecParameterSpec = ECUtil.getECParameterSpec(openSSLProvider, "prime256v1");
ECPoint ecPoint = ECUtil.decodePoint(decodedPublicKey, ecParameterSpec.getCurve());
ECPublicKeySpec pubSpec = new ECPublicKeySpec(ecPoint, ecParameterSpec);
ECPublicKey ecPublicKey = (ECPublicKey)keyFactory.generatePublic(pubSpec);
return ecPublicKey;
}
返回的get算法
是EC
。返回的getFormat
是X.509
。这个的getEncoded
值是-
[48,89,48,19,6,7,42,-122,72,-50,61,2,1,6,8,42,
-122,72,-50,61,3,1,7,3,66,0,4,0,-41,-4,96,23,
-89,77,-13,-1,-102,116,-28,-19,126,-94,-98,-75,
40,-112,37,-30,63,84,-38,-64,103,2,114,120,-89,
-2,-122,72,2,50,20,101,55,-108,-54,2,-31,-94,23,
-61,-3,-86,-107,57,-23,-105,41,0,-82,8,-17,-64,
37,-80,-5,104,58,47,-114]
忽略两个 EC 生成的密钥之间的差异。BouncyCastle在ECDH KeyGenerator中做了什么?
DH是一个KeyAgreement,我假设它正在生成一个EC密钥并通过DH KeyAgreement运行它 - 但是当KeyGenerator规范中没有指定任何内容时,它初始化为私钥是什么?
而且为什么当我对两个提供者使用EC算法时,当两个提供者都使用prime256v1
规范时,同一算法会得到不同的结果?我认为这些至少是相等的。
编辑:
ECUtil来自< code > sun . security . util . ECU til 。
对于在我的示例中BC和JavaSecurity Library共享一个通用名称的任何类(例如ECPoint)-它始终是JavaSecurity Library。只有当类以bouncyCastle路径(例如org.bouncycastle.jce.interfaces.ECPublicKey)为前缀时,它才是BC类。openSSLProvider是Conscrypt库中OpenSSLProvider的一个实例。
该项目可以在这里找到。
https://github.com/google/conscrypt
要安装的pom在这里-
<dependency>
<groupId>org.conscrypt</groupId>
<artifactId>conscrypt-openjdk-uber</artifactId>
<version>2.1.0</version>
</dependency>
///
import org.conscrypt.OpenSSLProvider;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import sun.security.util.ECUtil;
Security.addProvider(new BouncyCastleProvider());
Security.addProvider(new OpenSSLProvider());
ECUtil.getECParameterSpec(new OpenSSLProvider, "prime256v1");
编辑:
完整的最小可重复示例-
编辑编辑编辑:
示例现在包括手动加载公钥,而不是使用KeyFactory。
手动加载 BC 公钥时,它的编码值与通过密钥工厂加载时 Conscrypt 公钥的编码值匹配。
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.provider.JCEECPublicKey;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.conscrypt.OpenSSLProvider;
import sun.security.util.ECUtil;
import java.io.IOException;
import java.security.*;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.util.*;
public class Main {
public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, IOException {
Security.addProvider(new BouncyCastleProvider());
Security.addProvider(new OpenSSLProvider());
String pubKey = "BADX_GAXp03z_5p05O1-op61KJAl4j9U2sBnAnJ4p_6GSAIyFGU3lMoC4aIXw_2qlTnplykArgjvwCWw-2g6L44";
ECPublicKey publicKey = (ECPublicKey)loadPublicKey(pubKey, "Conscrypt");
org.bouncycastle.jce.interfaces.ECPublicKey publicKeyBC = (org.bouncycastle.jce.interfaces.ECPublicKey)loadPublicKey(pubKey, "BC");
org.bouncycastle.jce.interfaces.ECPublicKey publicKeyBC2 = (org.bouncycastle.jce.interfaces.ECPublicKey) loadPublicKeyManually(pubKey);
System.out.println(Arrays.toString(publicKey.getEncoded()));
System.out.println(Arrays.toString(publicKeyBC.getEncoded()));
System.out.println(Arrays.toString(publicKeyBC2.getEncoded()));
}
public static PublicKey loadPublicKey(String encodedPublicKey, String provider) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException, IOException {
Base64.Decoder base64Decoder = Base64.getUrlDecoder();
byte[] decodedPublicKey = base64Decoder.decode(encodedPublicKey);
KeyFactory keyFactory = KeyFactory.getInstance("EC", provider);
ECParameterSpec ecParameterSpec = ECUtil.getECParameterSpec(new OpenSSLProvider(), "prime256v1");
ECPoint ecPoint = ECUtil.decodePoint(decodedPublicKey, ecParameterSpec.getCurve());
ECPublicKeySpec pubSpec = new ECPublicKeySpec(ecPoint, ecParameterSpec);
ECPublicKey ecPublicKey = (ECPublicKey)keyFactory.generatePublic(pubSpec);
return ecPublicKey;
}
public static PublicKey loadPublicKeyManually(String encodedPublicKey) {
Base64.Decoder base64Decoder = Base64.getUrlDecoder();
byte[] decodedPublicKey = base64Decoder.decode(encodedPublicKey);
ECNamedCurveParameterSpec parameterSpec = ECNamedCurveTable.getParameterSpec("prime256v1");
org.bouncycastle.jce.spec.ECPublicKeySpec ecPublicKeySpec = new org.bouncycastle.jce.spec.ECPublicKeySpec(
parameterSpec.getCurve().decodePoint(decodedPublicKey),
parameterSpec
);
org.bouncycastle.jce.interfaces.ECPublicKey ecPublicKey = new JCEECPublicKey(
"EC",
ecPublicKeySpec
);
return ecPublicKey;
}
}
这两种公钥表示本质上是等价的。两者都是RFC 5280中描述的DER编码的SubjectPublicKeyInfo结构的实例。这个结构不仅包含公钥,还包含一些描述公钥算法上下文的元数据。对于其中一种形式,元数据简单地说明了上下文是“素数256v1”曲线。另一方面,提供了该曲线的所有参数。公钥本身作为两种形式的最后一部分出现,正如您所看到的,它们是相同的。
您拥有的是同一公钥的3种不同表示形式。base-64 编码字符串仅包含一个根据 SEC 1 第 2.3.3 节编码的 4 型(未压缩)椭圆曲线点。您在 sun.security.util.ECUtil
类中发现了一个未记录且不受支持的 API,以将其转换为公钥。
我不完全确定你关于私钥的问题是什么。对于包括ECDH的DH方案,私钥只是从基础组顺序范围中“安全”选择的整数。然后通过将该整数乘以曲线的基点(在椭圆曲线意义上)来计算公钥。结果公钥也是曲线上的一个点。
我正在尝试在BouncyCastle中导入公共和私有ECDH密钥。为了导入公钥,我使用了下面的C#代码,代码运行良好: 公钥:042E3E5CCF6B9AB04BE7A22F3FACCDE73C87E87155394A34815408A896CA18A374DAC669AF36220FC863767F4AF47507C5BC221FC4A19874DAF39B074E3EB8 私钥:be3f9bf
我正在尝试使用BouncyCastle在运行mbedTLS和Java的嵌入式设备之间进行ECDH。当我比较生成的密钥长度时,我得到了由mbedTLS制作的66字节密钥和由BC制作的65字节密钥。附加伪代码: MbedTLS: 当我将MbedTLS密钥加载到Java中时,它会抛出java.lang.IllegalArgumentException:无效的点编码0x41: 我尝试在Java和MbedT
我正在尝试创建一个公钥以允许我推送到Git,但我的. ssh文件夹尚未创建。 以下是我运行的命令: $ssh-keygen-t rsa-Cemaill@me.com 生成公共/私有rsa密钥对 输入保存密钥的文件(/h/.ssh/id\u rsa): 这就是H:驱动器配置、数据、配置文件、配置文件中的全部内容。V2 我认为有一个问题,因为当我得到提示输入文件,其中保存密钥(/h//. ssh/id
我试图在Android(Java)中实现ECDH加密/解密和JWE。 我找到了jose4j和Nimbus JOSE库,它们旨在做我需要的一切,但似乎比我想象的更具挑战性。 如果有人熟悉的话,那就是3D安全2.0。。。 在以下规范中: SDK=本地端 DS=目录服务器(另一边) 接下来是规范: 给定:P(DS)-EC公钥(以PEM格式提供,可以转换为PublicKey或JWK) 生成新的短暂密钥对(
问题内容: 我正在用Python编写程序,以通过安装程序分发给Windows用户。 该程序需要能够每天下载使用用户公钥加密的文件,然后再解密。 因此,我需要找到一个Python库,该库将允许我生成公共和私有PGP密钥,并解密使用该公共密钥加密的文件。 pyCrypto是否会做这件事(文档模糊)?还有其他纯Python库吗?使用任何语言的独立命令行工具如何? 到目前为止,我所看到的只是GNUPG,但
我试图学习并在java中实现JWE来解决问题。我试图理解内容加密密钥是如何使用特定算法生成的(比如RSA-PKCS1\u 1.5)。 我知道如何使用密钥生成器生成一对密钥,然后使用公钥进行加密,使用私钥进行解密。此外,我知道如何通过给出声明来创建简单的JWT令牌,以及如何对其进行签名。我试着遵循以下步骤: 消息加密过程如下: 生成随机内容加密密钥(CEK)。CEK的长度必须至少等于所需加密密钥的长