XML 簽名驗證的基本概念

Adobe AIR 1.5 以及更新的版本

如需瞭解驗證 XML 簽章的快速說明與程式碼範例,請到 Adobe Developer Connection 參閱下列快速入門文章:

Adobe® AIR® 提供了 XMLSignatureValidator 類別和 IURIDereferencer 介面來驗證 XML 簽名。XMLSignatureValidator 類別所接受的 XML 語法是 W3C 建議事項之「XML 簽章語法及處理」(XML-Signature Syntax and Processing) 的子集 (因為只有一個建議的子集受到支援,所以並非所有合法簽名都可以驗證)。AIR 並不提供 API 來建立 XML 簽名。

XML 簽名驗證類別

XML 簽名驗證 API 包括下列類別:

套件

類別

flash.security

XMLSignatureValidator 字串常數是在下列類別中定義:

flash.events

使用 XML 簽名驗證類別

若要使用 XMLSignatureValidator 類別來驗證 XML 簽名,您必須:

  • 建立 XMLSignatureValidator 物件

  • 提供 IURIDereferencer 介面的實作。XMLSignatureValidator 物件會呼叫 IURIDereferencer 的 dereference() 方法,將各個參照的 URI 傳至簽名中。 dereference() 方法必須解析 URI 並傳回參照的資料 (可能與簽名位於相同的文件裡,也可能在某個外部資源中)。

  • 根據應用程式的需要來設定 XMLSignatureValidator 物件的憑證信任、撤銷檢查和參照驗證設定。

  • complete error 事件新增偵聽程式。

  • 呼叫 verify() 方法,並傳入要驗證的簽名。

  • 處理 complete error 事件並對結果進行解譯。

下列範例將實作一個 validate() 函數來驗證 XML 簽名的有效性。以這種方式設定 XMLSignatureValidator 屬性,則簽署憑證必定會位於系統信任儲存區,或鍊結到信任儲存區中的某個憑證。此外,這個範例也假設有個名為 XMLDereferencer 的 IURIDereferencer 類別存在。

private function validate( xmlSignature:XML ):void 
{ 
    var verifier:XMLSignatureValidator = new XMLSignatureValidator(); 
    verifier.addEventListener(Event.COMPLETE, verificationComplete); 
    verifier.addEventListener(ErrorEvent.ERROR, verificationError); 
    try 
    { 
        verifier.uriDereferencer = new XMLDereferencer(); 
 
        verifier.referencesValidationSetting = 
            ReferencesValidationSetting.VALID_IDENTITY; 
        verifier.revocationCheckSetting = RevocationCheckSettings.BEST_EFFORT; 
        verifier.useSystemTrustStore = true; 
         
        //Verify the signature 
        verifier.verify( xmlSignature ); 
    } 
    catch (e:Error) 
        { 
            trace("Verification error.\n" + e); 
        } 
} 
 
//Trace verification results 
private function verificationComplete(event:Event):void 
 
    var signature:XMLSignatureValidator = event.target as XMLSignatureValidator; 
    trace("Signature status: " + signature.validityStatus + "\n"); 
    trace("  Digest status: " + signature.digestStatus + "\n"); 
    trace("  Identity status: " + signature.identityStatus + "\n"); 
    trace("  Reference status: " + signature.referencesStatus + "\n"); 
} 
 
private function verificationError(event:ErrorEvent):void 
{ 
    trace("Verification error.\n" + event.text);                 
}

XML 簽名驗證程序

當您呼叫 XMLSignatureValidator 的 verify() 方法時,AIR 會執行下列步驟:

  • 執行階段會使用簽署憑證的公開金鑰對簽名的密碼編譯完整性進行驗證。

  • 執行階段會根據 XMLSignatureValidator 物件目前的設定來建立憑證的密碼編譯完整性、身分和可靠性。

    簽署憑證中的信任設定就是驗證程序是否完整的關鍵。簽名驗證是透過一個定義完善的密碼編譯程序來進行,但簽署憑證的可靠與否無法透過演算法來判斷。

    一般來說,有三種方法能判斷憑證是否可靠:

    • 依賴憑證授權單位和作業系統信任儲存區。

    • 直接向簽署者取得另一份憑證來做為憑證的信任錨點,或是取得充足的資訊 (例如公開金鑰) 來確實地識別憑證。

    • 詢問應用程式的使用者是否信任目前的憑證。這樣的詢問對自我簽署的憑證並無用處,因為此類憑證裡的識別資訊並不可靠。

  • 執行階段會對簽署資料的密碼編譯完整性進行驗證。

    簽署資料可藉助 IURIDereferencer 的實作來進行驗證。針對簽名文件每一個參考,IURIDereferencer 實作的 dereference() 方法都會受到呼叫。 dereference() 方法所傳回的資料可用來算出參考的摘要。系統會將這個摘要值拿來與簽名文件記錄的摘要進行比較。如果摘要相符,就表示資料自簽署後未曾遭到竄改。

    仰賴 XML 簽名結果時有一個重要考量,就是只有受到簽署的內容才是安全的。讓我們以一份列出套件中所含檔案的簽署清單為例。當 XMLSignatureValidator 為簽名進行驗證時,只會檢查清單本身是否未曾遭到竄改。檔案中的資料並沒有受到簽署,所以即使這份清單所參照的檔案已遭變更或刪除,簽名仍可通過驗證。

    備註: 若要對此類清單中的檔案進行驗證,您可以計算檔案資料的摘要 (與清單使用相同的雜湊演算法計算),然後將結果拿來與簽署清單中的摘要進行比較。在某些情況下,您也應檢查是否有任何額外的檔案。

解譯驗證結果

驗證的結果是由 XMLSignatureValidator 物件的狀態屬性負責回報,而這些屬性可以在驗證工具物件傳送 complete 事件後讀取。共有四種狀態屬性,包括: validityStatus digestStatus identityStatus referencesStatus

validityStatus 屬性

validityStatus 屬性負責回報簽名的整體有效性。 validityStatus 的值根據其它三種狀態屬性而定,可能為:

  • valid — 如果 digestStatus identityStatus referencesStatus 均為 valid

  • invalid — 如果有一或多個個別狀態屬性為 invalid

  • unknown - 如果有一或多個個別狀態屬性為 unknown 且沒有個別狀態為 invalid

digestStatus 屬性

digestStatus 屬性負責回報訊息摘要的密碼編譯驗證結果。 digestStatus 屬性的值可能為:

  • valid — 如果簽名文件本身自簽署後未曾遭到竄改。

  • invalid - 如果簽名文件已變更或格式不正確。

  • unknown — 如果 verify() 方法完成時並非沒有發生錯誤。

identityStatus 屬性

identityStatus 屬性負責回報簽署憑證的狀態。這個屬性的值根據幾個因素而定,包括:

  • 憑證的密碼編譯完整性

  • 憑證是否已過期或撤銷

  • 憑證是否在目前的電腦上受到信任

  • XMLSignatureValidator 物件的狀態 (例如:是否有新增其它憑證來建立信任鍊結、那些憑證是否受到信任,以及 useSystemTrustStore revocationCheckSettings 屬性的值)

identityStatus 屬性可能具有下列值:
  • valid — 簽署憑證必須符合下列條件才視為有效:

    • 簽署憑證必須從未遭到竄改。

    • 除非簽名具有有效的時間戳記,否則簽署憑證不得是已過期或已撤銷。如果簽名具有時間戳記,則只要憑證在文件簽署時為有效,即會被視為有效 (時間戳記服務用來簽署時間戳記的憑證,必須鏈結到使用者電腦上受信任的根憑證)。

    • 簽署憑證受到信任。如果某個憑證位於系統信任儲存區中,或鍊結至系統信任儲存區中的其它憑證,而且 useSystemTrustStore 屬性設為 true,該憑證即受到信任。您也可以使用 XMLSignatureValidator 物件的 addCertificate() 方法來指定信任某個憑證。

    • 而實際上,這個憑證就是簽署憑證。

  • invalid — 憑證已過期或撤銷 (且無任何時間戳記可證明簽署時的有效性),或憑證已遭竄改。

  • unknown — 憑證並非無效,但也並未受到信任。例如,自我簽署的憑證就會被回報為 unknown (除非有受到明確的信任)。如果 verify() 方法完成時並非沒有發生錯誤,或是因為簽名摘要無效而沒有檢查身分, identityStatus 同樣也會回報為 unknown

referencesStatus 屬性

referencesStatus 屬性會針對簽名中 SignedData 元素的各個參照來回報其密碼編譯完整性。

  • valid — 如果針對簽名中各個參照所算出的摘要完全符合 XML 簽名中所對應的摘要。 valid 的狀態表示簽署資料未曾遭到竄改。

  • invalid — 如果有任何算出的摘要不符合簽名的對應摘要。

  • unknown — 如果尚未檢查參照摘要。如果整體的簽名摘要為 invalid 或簽署憑證為無效時,便不檢查參照。如果 identityStatus unknown ,則參照只有在 referencesValidationSetting validOrUnknown 時才會受到檢查。