Skip to content

MS_SAMLSignatureEncryption

nishi_74322014 edited this page Aug 12, 2026 · 1 revision

SAML Signature or Encryption

概要

汎用認証サイトに SAML2.0を実装するため仕様を読む。

  • ターゲットは SP Initiated な Web Browser SSO Profile に絞る。
  • ココに書いた情報は、SAML の Core の範囲。

SAML and XML Signature Syntax and Processing

SAML の XML署名・暗号に関する処理。

  • SAML ではデジタル署名は必ずしも必要ではない。

    • Message 内の Assertion など署名が継承されている場合。
    • 仲介者を通過しない Binding で、セキュアチャネルで認証されたメッセージ。
  • 署名するケース
    仲介者を通過する場合は署名するべき。

    • UA などの仲介者
    • IdP 以外から取得する Assertion
  • 署名の方法

    • 基本は、XML デジタル署名を使用する。
    • S/MIME や signed Java objects を使用してもイイ。

Signing Assertions

Assertion の署名ができる。

Request/Response Signing

Request / Response の署名ができる。

Signature Inheritance

簡単に言って、

  • <ds:Signature> 要素を持つ親要素からその子要素すべてが署名されている。
  • XML 文書のルート要素であってもなくてもかまわない

補足(署名継承は「そう見える」だけ): 「親を署名したから子も守られる」
のは、受信側が署名検証済みのノードから値を読み出す限りである。

実際には、<Response> にだけ署名がある場合、
内側の <Assertion>単体では取り出せない(署名がない)。
このため、

  • <Response> の署名を検証したなら、その署名対象ノード配下の
    <Assertion> だけを使う
  • 文書全体から XPath で <Assertion> を再検索してはならない

が鉄則になる。これを守らないと
**XML Signature Wrapping(XSW)**が成立する
XML署名・暗号を参照)。

実装としては「<Response><Assertion> のどちらに署名があるか」を
明示的に判定し、署名の無い方の値を信用しない設計にする。

XML Signature Profile

XML Signature 仕様 [XMLSig] は、
柔軟性と数多くの選択肢を備えた
データ署名の一般的な XML 構文を規定する。

Signing Formats and Algorithms

SAML では以下の XML署名・暗号を行う。

  • Enveloped 署名を採用する。
  • アルゴリズムは以下で識別される
    http://www.w3.org/2000/09/xmldsig#rsa-sha1

補足(最新化:SHA-1 は使わない): 仕様の既定は rsa-sha1 だが、
**SHA-1 は 2017 年に実際の衝突が実証(SHAttered)**されており、
現在は使用してはならない。

用途 現在使うべきアルゴリズム URI
SignatureMethod http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
DigestMethod http://www.w3.org/2001/04/xmlenc#sha256

IdP 側で SHA-256 署名に切り替えるだけでなく、
SP 側で SHA-1 署名を「拒否」する設定にすることが重要である。
受け付けたままでは、ダウングレードで無意味になる。

References

署名したルート要素の ID 属性を <ds:SignedInfo><ds:Reference> 要素に含める。

補足: <ds:Reference URI="#_xxxx"> の形になる。
ここで URI=""(空 = 文書全体)や外部 URI を許してはならない
検証対象を攻撃者が制御できるようになる。

Canonicalization Method

オブジェクトに署名する前に使用された標準化アルゴリズム。
SAML では Exclusive C14Nhttp://www.w3.org/2001/10/xml-exc-c14n#)を使う。

補足(なぜ Exclusive か): <Assertion>
<Response> から取り出されたり、別の文書に埋め込まれたりする。
通常の C14N では祖先要素の名前空間宣言を取り込んでしまうため、
文脈が変わると署名が壊れる。
Exclusive C14N は祖先の名前空間を引きずらないので、
署名済みの断片を移動できる(詳細は
XML署名・暗号)。

Transforms

Enveloped 署名には、

  • 署名変換(enveloped-signature
  • 排他的標準化変換(xml-exc-c14n#

以外の変換が含まれていてはならない。

移行メモ(正誤): 元ページは

エンベロープドには、署名変換以外の変換/排他的標準化変換 が含まれていてはならない。

と読める書き方になっていたが、仕様の趣旨は
許されるのは enveloped-signature 変換と Exclusive C14N 変換だけ」である。
上のとおり改めた。

補足: この制限は重要で、XSLT 変換や XPath 変換を禁じている
これらを許すと、署名検証時に任意のコードが実行されうる
(XSLT はチューリング完全であり、DoS や情報漏えいの入口になる)。

KeyInfo

SAML では、<ds:KeyInfo> はオプション。

補足(<KeyInfo> の証明書で検証してはならない): メッセージに
<ds:X509Certificate> が同梱されているからといって、
その証明書で署名を検証してはならない
攻撃者が自分の鍵で署名し、自分の証明書を同梱すれば通ってしまう。

正しくは、

  1. **メタデータで事前に受け取った証明書(または公開鍵)**を信頼の起点にする。
  2. メッセージ中の <KeyInfo> は、
    どの登録済み鍵を使うか」のヒントとしてのみ使う(照合する)。

JWSjku / x5u を鵜呑みにしてはならないのと同じ問題である。

Example

<Response
  IssueInstant="2003-04-17T00:46:02Z" Version="2.0"
  ID="_c7055387-af61-4fce-8b98-e2927324b306"
  xmlns="urn:oasis:names:tc:SAML:2.0:protocol"
  xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:Issuer>https://www.opensaml.org/IDP</saml:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  <ds:SignedInfo>
    <ds:CanonicalizationMethod
      Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
    <ds:SignatureMethod
      Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
    <ds:Reference URI="#_c7055387-af61-4fce-8b98-e2927324b306">
      <ds:Transforms>
        <ds:Transform
          Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
        <ds:Transform
          Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
          <InclusiveNamespaces
            PrefixList="#default saml ds xs xsi"
            xmlns="http://www.w3.org/2001/10/xml-exc-c14n#"/>
        </ds:Transform>
      </ds:Transforms>
      <ds:DigestMethod
        Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
      <ds:DigestValue>...</ds:DigestValue>
    </ds:Reference>
  </ds:SignedInfo>
  <ds:SignatureValue>...</ds:SignatureValue>
  <ds:KeyInfo>
    <ds:X509Data>
      <ds:X509Certificate>...</ds:X509Certificate>
    </ds:X509Data>
  </ds:KeyInfo>
</ds:Signature>
<Status>
  <StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</Status>
<Assertion ID="_a75adf55-01d7-40cc-929f-dbd8372ebdfc"
  IssueInstant="2003-04-17T00:46:02Z" Version="2.0"
  xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
  <Issuer>https://www.opensaml.org/IDP</Issuer>
  <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <ds:SignedInfo>
      <ds:CanonicalizationMethod
        Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
      <ds:SignatureMethod
        Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
      <ds:Reference URI="#_a75adf55-01d7-40cc-929f-dbd8372ebdfc">
        <ds:Transforms>
          <ds:Transform
            Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
          <ds:Transform
            Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
            <InclusiveNamespaces
              PrefixList="#default saml ds xs xsi"
              xmlns="http://www.w3.org/2001/10/xml-exc-c14n#"/>
          </ds:Transform>
        </ds:Transforms>
        <ds:DigestMethod
          Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
        <ds:DigestValue>...</ds:DigestValue>
      </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue>...</ds:SignatureValue>
    <ds:KeyInfo>
      <ds:X509Data>
        <ds:X509Certificate>...</ds:X509Certificate>
      </ds:X509Data>
    </ds:KeyInfo>
  </ds:Signature>
  <Subject>
    <NameID
      Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
      scott@example.org
    </NameID>
    <SubjectConfirmation
      Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"/>
  </Subject>
  <Conditions NotBefore="2003-04-17T00:46:02Z"
    NotOnOrAfter="2003-04-17T00:51:02Z">
    <AudienceRestriction>
      <Audience>http://www.opensaml.org/SP</Audience>
    </AudienceRestriction>
  </Conditions>
  <AuthnStatement AuthnInstant="2003-04-17T00:46:00Z">
    <AuthnContext>
      <AuthnContextClassRef>
        urn:oasis:names:tc:SAML:2.0:ac:classes:Password
      </AuthnContextClassRef>
    </AuthnContext>
  </AuthnStatement>
</Assertion>
</Response>

移行メモ: 元ページの <saml:Issuer>
値の末尾に余分な " が付いていた(.../IDP")ため取り除いた。
また変換アルゴリズムの URI が #envelopedsignature
ハイフン抜けになっていたので #enveloped-signature に正した。

この例は <Response><Assertion> の両方に署名があるケースである。
この「二重署名」が、後述の SignedXml の問題を引き起こす。

<Assertion ID="_c42ed101-0051-48ad-a678-8cb58dee03f6" ...>
  <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <ds:SignedInfo>
      <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
      <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
      <ds:Reference URI="#_c42ed101-0051-48ad-a678-8cb58dee03f6">
        <ds:Transforms>
          <ds:Transform
            Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
          <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
        </ds:Transforms>
        <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        <ds:DigestValue>wlE4Jf0Z8Z+2OyWE69RRH81atZ8=</ds:DigestValue>
      </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue>...</ds:SignatureValue>
    <ds:KeyInfo>
      <ds:X509Data>
        <ds:X509Certificate>...</ds:X509Certificate>
      </ds:X509Data>
    </ds:KeyInfo>
  </ds:Signature>
</Assertion>

SAML and XML Encryption Syntax and Processing

  • SOAP Binding は TLS や SOAP Message Security 機密保護機構の使用をサポート。

  • <SubjectConfirmationData> 内の <ds:KeyInfo> 要素を使用し
    <SubjectConfirmation> 秘密を保護できる。

  • その他、以下を暗号化できる。

暗号化対象 格納先
<BaseID> または <NameID> 要素 <EncryptedID><xenc:EncryptedData><xenc:EncryptedKey>
<Attribute> 要素 <EncryptedAttribute><xenc:EncryptedData><xenc:EncryptedKey>
<Assertion> 要素全体 <EncryptedAssertion><xenc:EncryptedData><xenc:EncryptedKey>

General Considerations

要素の暗号化は XML Encryption [XMLEnc] の使用により提供される
XML署名・暗号)。

Combining Signatures and Encryption

  • XML Encryption と XML Signature の使用を結合することができる(MAY)。

  • 署名・暗号化の順番

    • <Assertion> の場合、署名(<ds:Signature> 要素を追加)→ 暗号化
    • <BaseID> / <NameID> / <Attribute> の場合、暗号化 → 署名

補足(順序の理屈): 一見矛盾しているようだが、
どちらも「署名の対象が、受信側が実際に検証できる形になっている
という条件を満たすための帰結である。

  • <Assertion> 全体を暗号化する場合、
    中身に署名してから丸ごと暗号化する(復号して初めて署名を検証する)。
    JWT の Nested JWT(署名 → 暗号化)と同じ順序。

  • <NameID> など一部だけを暗号化する場合、
    先に暗号化して <EncryptedID> にしてから、
    それを含む <Assertion> に署名する。
    逆順にすると、暗号化によって署名対象のバイト列が変わり
    署名が壊れる

なお、暗号化されている部分は署名検証の対象になっていない
ケースがありうる(<EncryptedAssertion> の外側に署名がない等)。
復号した中身の署名を必ず検証すること。

参考

oasis-open.org

https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf

5 SAML and XML Signature Syntax and Processing
5.1 Signing Assertions
5.2 Request/Response Signing
5.3 Signature Inheritance
5.4 XML Signature Profile
5.4.1 Signing Formats and Algorithms
5.4.2 References
5.4.3 Canonicalization Method
5.4.4 Transforms
5.4.5 KeyInfo
5.4.6 Example

6 SAML and XML Encryption Syntax and Processing
6.1 General Considerations
6.2 Combining Signatures and Encryption

Tags: 移行, IT国際標準, 認証基盤, クレームベース認証, SAML

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally