#SAML アサーションの暗号化とは?
弊社OSSテクノロジではOpenAMの開発とサポートを行っています。
SAMLといえばOpenAM、OpenAMといえばSAMLという訳ではありませんが、SAMLについて少し書きます。
##SAMLアサーション?
SAMLについては、今更詳しく書くことはしませんが、サラッと関連事項だけフォローしておきます。
SAMLとはフェデレーション(シングルサインオン)に使われているプロトコルで、G-SuitesやOffice365、Salesforce、AWSなど主要なクラウドサービスでサポートされています。
SAMLにはIdP(認証サーバー)と、SP(認証を依頼し、認証情報を使うアプリケーションサーバー)の2役ありまして、このIdPからSPへ流れる認証情報をアサーションと呼んでいます。
SAMLアサーションはXML情報なので、暗号化にはXMLの暗号化規約xmlencを利用しています。
暗号化しない時のSAMLアサーションをFirefoxのアドオン SAML-tracer で見てみます。
いたって普通のXMLです。
SAMLアサーションの暗号化はこのXMLの大事な部分を暗号化してしまおうとういことです。
##XML 暗号化の仕組み
ではどのようにXMLを暗号化するかというと、2種類の暗号方式が使われています。
###公開鍵暗号方式
IDPからSPへ渡される共通鍵を暗号化するのに使います。
共通鍵暗号方式に比べて計算に時間がかかるため、SAMLアサーション全体を暗号化するのではなく、共通鍵のみを暗号化するのに使われます。
暗号に使った共通鍵は、IdPがSPの公開鍵で暗号化してSAMLアサーションと一緒に送ります。
###共通鍵暗号方式
SAMLアサーションを暗号化するのに使います。
公開鍵暗号方式にくらべて計算時間が短いため、SAMLアサーション全体を暗号化するのに使われます。
#SAMLアサーションの暗号化を試して見る
SAMLアサーションの暗号化がわかったところで、設定して試してみます。
##OpenAMでのSAMLアサーション暗号化の設定
特に難しいことはありません、以下のチェックボックをチェックするだけです。
先程と同じように暗号化した時のSAMLアサーションをFirefoxのアドオン SAML-tracer で見てみます。
画像だと分かりにくいので、一部抜粋します。
先程説明しました2種類の暗号化方式が使われています。
共通鍵暗号方式(SAMLアサーションの暗号)
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />
公開鍵暗号方式(共通鍵の暗号)
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
あぁ...エラー
若干上の説明でネタバレしてますが、今回SPに使ったソフトウェアはshibbolethです。
OpenAMからのSAMLアサーションを受けた時に、以下のエラー画面が出ます。
HTMLのエラーメッセージだけでは詳細が分からないので、/var/log/shibboleth/shibd.logをみるとshib.logxmlenc#rsa-1_5 は許されないぞと...復号化時にエラーになってます。
2018-11-30 16:44:30 WARN XMLTooling.Decrypter [2] [default]: XMLSecurity exception while decrypting key: XSECAlgorithmMapper::mapURIToHandler - URI http://www.w3.org/2001/04/xmlenc#rsa-1_5 disallowed by whitelist/blacklist policy
#機能が無いならコードを追加すればいいじゃない
パンが無いならケーキを食べればいいじゃないの法則
##RSAES-PKCS1-v1_5は無しの方向で...
SAMLアサーションの暗号化はあまり人気が無い技術で、いろいろなWebサービスでは「SAMLの暗号化はオフにすること」なんて注釈があったりしますが、、、
RSA-1.5が許されない世界なら、RSA-OAEPを使えるように改造するのです。
とりあえず、コードを見てみるのです。
OpenAMのコードでは以下のような実装です。RSAなら1.5決め打ち。
FMEncProvider.java
if (publicKeyEncAlg.equals(EncryptionConstants.RSA)) {
cipher = XMLCipher.getInstance(XMLCipher.RSA_v1dot5);
} else if ...
後方互換性を気にしないで、単純にRSA-OAEPにしたいだけなら以下のようにするのもアリです。
if (publicKeyEncAlg.equals(EncryptionConstants.RSA)) {
cipher = XMLCipher.getInstance(XMLCipher.RSA_OAEP);
} else if ...
弊社はアップデートするお客様までフォローする必要があるので、高度な設定にuseRSAOAEPという設定を追加して、そのパラメーターが true だったら RSA_OAEPで暗号化するようなコードとします。
if (publicKeyEncAlg.equals(EncryptionConstants.RSA)) {
if (useRSAOAEP) {
cipher = XMLCipher.getInstance(XMLCipher.RSA_OAEP);
} else {
cipher = XMLCipher.getInstance(XMLCipher.RSA_v1dot5);
}
##実食というかテスト
いままでと同じように、暗号化時のSAMLアサーションをFirefoxのアドオン SAML-tracer で見てみます。
スクリーンショットでは分かりにくいので抜粋します。
公開鍵暗号方式がrsa-oaep-mgf1pに変わったのがお分かりいただけるだろうか?
共通鍵暗号方式(SAMLアサーションの暗号)
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />
公開鍵暗号方式(共通鍵の暗号)
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" />
機能が欲しければ自分で書く、オープンソースの基本ですね。おはり