私は、セキュリティプロバイダとしてはBouncyCastleを使用しているアプリケーションがありますが、私は直接、OpenSSLを使用して別の1(Conscrypt)に切り替えたいです。私がいる問題は、私がECDHはBouncyCastleで提供するKeyGeneratorから「キー」を使用していますが、私の他のライブラリで同様のKeyGeneratorを持っていないということです。
私は、次の入力 - との両方の方法を使用してポイントを解読しようと思って両者を比較するには
改行は読みやすくするために追加します
BADX_GAXp03z_5p05O1-op61KJAl4j9U2sBnAnJ4p_6GSAIyFGU3lM
oC4aIXw_2qlTnplykArgjvwCWw-2g6L44
BouncyCastle METHOD-を使用して
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;
}
getAlgorithm
返されます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)I GET-
[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]
今Conscrypt METHOD-と
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;
}
getAlgorithm
返されます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がから来ていますsun.security.util.ECUtil
。
BCおよびJavaのセキュリティライブラリの両方が、私の例では、共通の名前を共有する場所の任意のクラス(例えばECPoint)のために - それは常にJavaのセキュリティライブラリです。クラスははBouncyCastleパス(例えばorg.bouncycastle.jce.interfaces.ECPublicKey)が付いている場合のみ、それはBCクラスです。openSSLProviderはConscryptライブラリからOpenSSLProviderのインスタンスです。
そのプロジェクトはここで見つけることができます。
https://github.com/google/conscrypt
そして、インストールするPOMはhere-です
<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;
}
}
2つの公開鍵の表現がある、本質的に同等。両方がで説明DER符号化されたSubjectPublicKeyInfoで構造体のインスタンスであるRFC 5280。この構造は、だけでなく、公開鍵でなく、公開鍵のアルゴリズムのコンテキストを記述するいくつかのメタデータが含まれています。いずれかの形式のメタデータは、単にコンテキストが「prime256v1」曲線であると述べています。他の場合、この曲線のすべてのパラメータが代わりに提供されています。公開鍵自体は、両方の形態の最後の部分として発生し、あなたが見ることができるように、彼らは同じです。
何が同じ公開鍵の合計で3つの異なる表現しているしています。ベース64エンコードされた文字列だけに従って符号化タイプ4(非圧縮)の楕円曲線点含まSEC 1セクション2.3.3。あなたには文書化されていないと、サポートされていないAPIを発見したsun.security.util.ECUtil
のPublicKeyにこれを有効にするクラス。
私は、あなたの質問には、秘密鍵何であるか、完全に一定ではありませんよ。ECDH含むDH方式のため、プライベートキーは、単に基礎となるグループの順序の範囲から「安全」選ばれた整数です。公開鍵は、その後、曲線のベースポイント(楕円曲線の意味で)この整数を乗算することによって計算されます。その結果、公開鍵はまた、曲線上の点です。