第28章 暗号(デジタル署名)
デジタル署名の暗号コンポーネント リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
Apache Camel 2.3 で利用可能
Apache Camel 暗号化エンドポイントと Java の Cryptographic エクステンションを使用すると、エクスチェンジのデジタル署名を簡単に作成できます。Apache Camel は、エクスチェンジのワークフローの 1 つの部分で交換用の署名を作成し、ワークフローの後半に署名を検証するために使用する柔軟なエンドポイントのペアを提供します。
Maven ユーザーは、このコンポーネントの
pom.xml に以下の依存関係を追加する必要があります。
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-crypto</artifactId>
<version>x.x.x</version>
<!-- use the same version as your Camel core version -->
</dependency>
Camel on EAP デプロイメント リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
このコンポーネントは、Red Hat JBoss Enterprise Application Platform (JBoss EAP) コンテナー上で簡素化されたデプロイメントモデルを提供する Camel on EAP (Wildfly Camel) フレームワークによってサポートされます。このモデルの詳細は、Deploying into a Web Server の Apache Camel on JBoss EAP の章を参照してください。
Camel 暗号化エンドポイントおよび Java の暗号化エクステンションを使用すると、エクスチェンジのデジタル署名を簡単に作成できます。ただし、Camel は柔軟なエンドポイントのペアも提供します。最初に、エクスチェンジの署名を作成してから、ワークフローの後半部分で署名を検証します。
たとえば、以下のように、JNDI にバインドするためのキーストアを読み込み、Camel が Bean レジストリーから検索できるようにします。
// Java
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream in = getClass().getResourceAsStream("/my-keystore.ks");
keystore.load(in, "my-keystore-password".toCharArray());
Certificate cert = keystore.getCertificate("my-certificate-alias");
KeyStoreParameters keystoreParameters = new KeyStoreParameters();
keystoreParameters.setPassword("my-keystore-password");
keystoreParameters.setResource("./my-keystore.ks");
InitialContext initialContext = new InitialContext();
initialContext.bind("signatureParams", keystoreParameters);
initialContext.bind("keystore", keystore);
initialContext.bind("myPublicKey", cert.getPublicKey());
initialContext.bind("myCert", cert);
initialContext.bind("myPrivateKey", keystore.getKey("my-certificate-alias", "my-keystore-password".toCharArray()));
以下は、エクスチェンジに署名し、検証する camel ルートです。
// Java
CamelContext camelContext = new DefaultCamelContext();
camelContext.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:sign")
.to("crypto:sign://basic?privateKey=#myPrivateKey")
.to("direct:verify");
from("direct:verify")
.to("crypto:verify://basic?publicKey=#myPublicKey")
.to("mock:result");
}
});
はじめに リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
デジタル署名は、非対称 Cryptographic 技術を使用してメッセージに署名します。(非常に)高レベルから、アルゴリズムは、特別なプロパティーと複合キーのペアを使用します。これは、1 つの鍵で暗号化されたデータは他のキーでのみ復号化できます。秘密鍵の 1 つは、密接に保護され、他の公開鍵がメッセージの検証に関心のある人に共有されている間、メッセージに署名するために使用されます。メッセージは、秘密鍵を使用してメッセージのダイジェストを暗号化することによって署名されます。この暗号化されたダイジェストは メッセージと共に送信されます。一方、ベリファイアはメッセージダイジェストを再計算し、公開鍵を使用して署名のダイジェストを復号化します。両方のダイジェストが一致する場合、ベリファイアは秘密鍵の所有者のみが署名を作成できることを認識します。
Apache Camel は、Java Cryptographic Extension からの Signature サービスを使用して、交換署名の作成に必要なすべての大きな暗号化レイテンシーを実行します。以下は、Cryptography、Message digests、および Digital Signatures のメカニズム、メッセージダイジェスト、および Digital Signatures の使用方法を説明する優れたソースです。
- Bruce Schneier's Applied Cryptography
- David Hook による Java の暗号開始
- The ever insightful, Wikipedia Digital_signatures
URI 形式 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
前述のように、Apache Camel は署名を作成および検証するための暗号化エンドポイントのペアを提供します。
crypto:sign:name[?options]
crypto:verify:name[?options]
crypto:signは署名を作成し、定数org.apache.camel.component.crypto.DigitalSignatureConstants.SIGNATURE、つまり Header キーに保存します。"CamelDigitalSignature".crypto:verifyはこのヘッダーの内容で読み取り、検証の計算を行います。
正しく機能させるには、署名して鍵のペアを共有し、
PrivateKey に署名し、PublicKey (またはそれを含む 証明書 )を検証する必要があります。JCE の使用は、これらのキーペアの生成が非常に簡単ですが、通常は KeyStore を使用してキーを格納し、共有することが最も安全です。DSL は、キーがどのように提供されるかについて非常に柔軟であり、さまざまなメカニズムを提供します。
crypto:sign エンドポイントは通常、あるルートと補完的な crypto:verify で定義されます。ただし、もう 1 つのルートの後に表示される例を簡潔にしています。記号と検証の両方を同時に設定すべきという意味はありません。
オプション リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
| 名前 | タイプ | デフォルト | 説明 |
|---|---|---|---|
algorithm
|
文字列
|
DSA
|
使用される JCE 署名アルゴリズムの名前。 |
alias
|
文字列
|
null
|
キーストアからキーを選択するために使用されるエイリアス名。 |
bufferSize
|
整数
|
2048
|
署名プロセスで使用されるバッファーサイズ |
certificate
|
証明書
|
null
|
エクスチェンジのペイロードの署名の検証に使用される証明書。このキーまたは公開鍵のいずれかが必要です。 |
keystore
|
keystore
|
null
|
署名および検証に使用されるキーおよび証明書を格納する JCE キーストアへの参照。 |
provider
|
文字列
|
null
|
使用する必要がある JCE セキュリティープロバイダーの名前。 |
privateKey
|
PrivatKey
|
null
|
エクスチェンジのペイロードの署名に使用される秘密鍵。 |
publicKey
|
PublicKey
|
null
|
エクスチェンジのペイロードの署名の検証に使用される公開鍵。 |
secureRandom
|
secureRandom
|
null
|
署名サービスの初期化に使用される SecureRandom オブジェクトへの参照。
|
password
|
char[]
|
null
|
キーストアのパスワード。 |
clearHeaders
|
文字列
|
true
|
検証操作後にメッセージから camel 暗号化ヘッダーを削除します(値は "true"/{{"false"}})できます。
|
1)raw キー リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
交換に署名して検証する最も基本的な方法は、以下のように KeyPair を使用することです。
from("direct:keypair").to("crypto:sign://basic?privateKey=#myPrivateKey", "crypto:verify://basic?publicKey=#myPublicKey", "mock:result");
キーへの参照を使用して Spring XML エクステンション でも同じことができます。
<route>
<from uri="direct:keypair"/>
<to uri="crypto:sign://basic?privateKey=#myPrivateKey" />
<to uri="crypto:verify://basic?publicKey=#myPublicKey" />
<to uri="mock:result"/>
</route>
2)キーストアとエイリアス。 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
JCE は、PrivateKeys と Certificates のペアを格納するために非常に汎用の KeyStore を提供し、それらを暗号化およびパスワードで保護します。これらは、エイリアスを取得 apis に適用して、そこから取得できます。キーストアにキーと証明書を取得する方法は複数あります。ほとんどの場合、これは外部の keytool アプリケーションで行います。これ は、keytool を使用して自己署名証明書と秘密鍵で KeyStore を作成するのに適した例です。
この例では、キーと bob によってエイリアスがついた証明書を持つキーストアを使用します。キーストアおよびキーのパスワードは 'letmein' です。
以下は、Fluent ビルダーを介してキーストアを使用する方法を示しています。また、キーストアを読み込み、初期化する方法も示しています。
from("direct:keystore").to("crypto:sign://keystore?keystore=#keystore&alias=bob&password=letmein", "crypto:verify://keystore?keystore=#keystore&alias=bob", "mock:result");
Spring ではも、ref を使用して実際のキーストアインスタンスを検索します。
<route>
<from uri="direct:keystore"/>
<to uri="crypto:sign://keystore?keystore=#keystore&lias=bob&assword=letmein" />
<to uri="crypto:verify://keystore?keystore=#keystore&lias=bob" />
<to uri="mock:result"/>
</route>
3)JCE プロバイダーとアルゴリズムの変更 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
署名アルゴリズムまたはセキュリティープロバイダーの変更は、名前を指定するための簡単です。選択したアルゴリズムと互換性のあるキーも使用する必要があります。
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(512, new SecureRandom());
keyPair = keyGen.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
// we can set the keys explicitly on the endpoint instances.
context.getEndpoint("crypto:sign://rsa?algorithm=MD5withRSA", DigitalSignatureEndpoint.class).setPrivateKey(privateKey);
context.getEndpoint("crypto:verify://rsa?algorithm=MD5withRSA", DigitalSignatureEndpoint.class).setPublicKey(publicKey);
from("direct:algorithm").to("crypto:sign://rsa?algorithm=MD5withRSA", "crypto:verify://rsa?algorithm=MD5withRSA", "mock:result");
from("direct:provider").to("crypto:sign://provider?privateKey=#myPrivateKey&provider=SUN", "crypto:verify://provider?publicKey=#myPublicKey&provider=SUN", "mock:result");
または
<route>
<from uri="direct:algorithm"/>
<to uri="crypto:sign://rsa?algorithm=MD5withRSA&rivateKey=#rsaPrivateKey" />
<to uri="crypto:verify://rsa?algorithm=MD5withRSA&ublicKey=#rsaPublicKey" />
<to uri="mock:result"/>
</route>
<route>
<from uri="direct:provider"/>
<to uri="crypto:sign://provider?privateKey=#myPrivateKey&rovider=SUN" />
<to uri="crypto:verify://provider?publicKey=#myPublicKey&rovider=SUN" />
<to uri="mock:result"/>
</route>
4)署名メッジヘッダーの変更 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
署名の保存に使用するメッセージヘッダーを変更することが望ましい場合があります。以下のように、ルート定義で異なるヘッダー名を指定できます。
from("direct:signature-header").to("crypto:sign://another?privateKey=#myPrivateKey&signatureHeader=AnotherDigitalSignature",
"crypto:verify://another?publicKey=#myPublicKey&signatureHeader=AnotherDigitalSignature", "mock:result");
または
<route>
<from uri="direct:signature-header"/>
<to uri="crypto:sign://another?privateKey=#myPrivateKey&ignatureHeader=AnotherDigitalSignature" />
<to uri="crypto:verify://another?publicKey=#myPublicKey&ignatureHeader=AnotherDigitalSignature" />
<to uri="mock:result"/>
</route>
5)バッファーサイズの変更 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
バッファーサイズを更新する必要がある場合...
from("direct:buffersize").to("crypto:sign://buffer?privateKey=#myPrivateKey&buffersize=1024", "crypto:verify://buffer?publicKey=#myPublicKey&buffersize=1024", "mock:result");
または
<route>
<from uri="direct:buffersize" />
<to uri="crypto:sign://buffer?privateKey=#myPrivateKey&uffersize=1024" />
<to uri="crypto:verify://buffer?publicKey=#myPublicKey&uffersize=1024" />
<to uri="mock:result"/>
</route>
6)キーを動的に指定します。 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
Recipient List または同様の EIP を使用する場合、エクスチェンジの受信者は動的に異なる場合があります。すべての受信者で同じキーを使用することは実行可能でも望ましい場合もあります。交換ごとに署名キーを動的に指定できると便利です。エクスチェンジは、署名前にターゲット受信者のキーで動的にエンリッチできます。これを容易にするために、署名メカニズムにより、以下のメッセージヘッダーを介してキーを動的に提供できます。
Exchange.SIGNATURE_PRIVATE_KEY,"CamelSignaturePrivateKey"Exchange.SIGNATURE_PUBLIC_KEY_OR_CERT,"CamelSignaturePublicKeyOrCert"
from("direct:headerkey-sign").to("crypto:sign://alias");
from("direct:headerkey-verify").to("crypto:verify://alias", "mock:result");
または
<route>
<from uri="direct:headerkey-sign"/>
<to uri="crypto:sign://headerkey" />
</route>
<route>
<from uri="direct:headerkey-verify"/>
<to uri="crypto:verify://headerkey" />
<to uri="mock:result"/>
</route>
再度、キーストアエイリアスを動的に提供することをお勧めします。ここでも、エイリアスをメッセージヘッダーに提供できます。
Exchange.KEYSTORE_ALIAS,"CamelSignatureKeyStoreAlias"
from("direct:alias-sign").to("crypto:sign://alias?keystore=#keystore");
from("direct:alias-verify").to("crypto:verify://alias?keystore=#keystore", "mock:result");
または
<route>
<from uri="direct:alias-sign"/>
<to uri="crypto:sign://alias?keystore=#keystore" />
</route>
<route>
<from uri="direct:alias-verify"/>
<to uri="crypto:verify://alias?keystore=#keystore" />
<to uri="mock:result"/>
</route>
ヘッダーは以下のように設定されます。
Exchange unsigned = getMandatoryEndpoint("direct:alias-sign").createExchange();
unsigned.getIn().setBody(payload);
unsigned.getIn().setHeader(DigitalSignatureConstants.KEYSTORE_ALIAS, "bob");
unsigned.getIn().setHeader(DigitalSignatureConstants.KEYSTORE_PASSWORD, "letmein".toCharArray());
template.send("direct:alias-sign", unsigned);
Exchange signed = getMandatoryEndpoint("direct:alias-sign").createExchange();
signed.getIn().copyFrom(unsigned.getOut());
signed.getIn().setHeader(KEYSTORE_ALIAS, "bob");
template.send("direct:alias-verify", signed);
以下も参照してください。
- 暗号化は データ形式としても利用できます。