2009-12-20 28 views
15

Tại nơi làm việc, chúng tôi có một ứng dụng web mà chúng tôi sẽ cần phải giao tiếp với ứng dụng web của một công ty khác bằng Đăng nhập một lần được SAML xác thực. Các ứng dụng web của chúng tôi được viết bằng PHP và rõ ràng là không liên quan đến lựa chọn ngôn ngữ mà công ty khác đang sử dụng. Tuy nhiên, tôi cần viết một API đơn giản mà công ty khác này có thể gửi các yêu cầu SOAP đến với các yêu cầu SAML và tạo ra một phản hồi SAML. Tôi đã viết nó từ đầu vì ba lý do: 1) không thực sự có nhiều tùy chọn cho tương tác SAML được viết bằng PHP ngay cả khi tôi muốn một, 2) nó giới hạn chi phí sẽ liên quan với việc thêm một thành phần của bên thứ ba khác và 3) tạo mọi thứ từ đầu thường giúp tôi hiểu rõ hơn và giúp tôi có khả năng thích nghi nhiều hơn trong tương lai nếu cần.Tôi cần biết gì về Chữ ký XML để SAML hoạt động?

Dù sao thì, tôi khá mới đối với tiêu chuẩn SAML, SOAP và XML nói chung, vì vậy tôi đã tự dạy mình khi tôi đi. Tôi đã hoàn thành API khá nhiều cho mục đích của chúng tôi, với một ngoại lệ mà công ty khác đã chỉ định rằng phản hồi của chúng tôi sẽ được yêu cầu ký kỹ thuật số với chứng chỉ (và yêu cầu chúng tôi nhận được tương tự sẽ được ký điện tử). Vì vậy, tôi đã cố gắng tìm ra cách xử lý/tạo ra các chữ ký XML, nhưng thành thật mà nói, nó hơi khó hiểu vì các thông số W3C không chính xác là đọc ánh sáng.

Mục 5.4.8 của tài liệu Assertions and Protocol for the OASIS Security Markup Language (SAML) V1.1 (tài liệu tôi đã đi, vì công ty khác cho biết họ sẽ sử dụng v1.1) bao gồm ví dụ về câu trả lời đã ký có chứa xác nhận đã ký, mà tôi sẽ bao gồm ở đây để tham khảo:

<Response IssueInstant="2003-04-17T00:46:02Z" MajorVersion="1" MinorVersion="1" 
Recipient="www.opensaml.org" ResponseID="_c7055387-af61-4fce-8b98-e2927324b306" 
xmlns="urn:oasis:names:tc:SAML:1.0:protocol" 
xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<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 samlp ds xsd 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>TCDVSuG6grhyHbzhQFWFzGrxIPE=</ds:DigestValue> 
    </ds:Reference> 
    </ds:SignedInfo> 
    <ds:SignatureValue>x/GyPbzmFEe85pGD3c1aXG4Vspb9V9jGCjwcRCKrtwPS6vdVNCcY5rHaFPYWkf+5EIYcPzx+pX1h43SmwviCqXRjRtMANWbHLhWAptaK1ywS7gFgsD01qjyen3CP+m3Dw6vKhaq1ed10BYyrIzb4KkHO4ahNyBVXbJwqv5pUaE4=</ds:SignatureValue> 
    <ds:KeyInfo> 
    <ds:X509Data> 
    <ds:X509Certificate>MIICyjCCAjOgAwIBAgICAnUwDQYJKoZIhvcNAQEEBQAwgakxCzAJBgNVBAYTA1VT ... 8I3bsbmRAUg4UP9hH6ABVq4KQKMknxu1xQxLhpR1y1GPdiowMNTrEG8cCx3w/w==</ds:X509Certificate> 
    </ds:X509Data> 
    </ds:KeyInfo> 
</ds:Signature> 
<Status><StatusCode Value="samlp:Success"/></Status> 
<Assertion AssertionID="_a75adf55-01d7-40cc-929f-dbd8372ebdfc" 
    IssueInstant="2003-04-17T00:46:02Z" Issuer="www.opensaml.org" 
    MajorVersion="1" MinorVersion="1" xmlns="urn:oasis:names:tc:SAML:1.0:assertion" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <Conditions NotBefore="2003-04-17T00:46:02Z" NotOnOrAfter="2003-04-17T00:51:02Z"> 
    <AudienceRestrictionCondition> 
    <Audience>http://www.opensaml.org</Audience> 
    </AudienceRestrictionCondition> 
    </Conditions> 
    <AuthenticationStatement AuthenticationInstant="2003-04-17T00:46:00Z" 
    AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:password"> 
    <Subject> 
    <NameIdentifier Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">[email protected]</NameIdentifier> 
    <SubjectConfirmation> 
    <ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</ConfirmationMethod> 
    </SubjectConfirmation> 
    </Subject> 
    <SubjectLocality IPAddress="127.0.0.1"/> 
    </AuthenticationStatement> 
    <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 samlp ds xsd 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>Kclet6XcaOgOWXM4gty6/UNdviI=</ds:DigestValue> 
    </ds:Reference> 
    </ds:SignedInfo> 
    <ds:SignatureValue>hq4zk+ZknjggCQgZm7ea8fI79gJEsRy3E8LHDpYXWQIgZpkJN9CMLG8ENR4Nrw+n7iyzixBvKXX8P53BTCT4VghPBWhFTSt9tHWu/AtJfOTh6qaAsNdeCyG86jmtp3TDMWuL/cBUj2OtBZOQMFn7jQ9YB7k1Iz3RqVL+wNmeWI4=</ds:SignatureValue> 
    <ds:KeyInfo> 
    <ds:X509Data> 
    <ds:X509Certificate>MIICyjCCAjOgAwIBAgICAnUwDQYJKoZIhvcNAQEEBQAwgakxCzAJBgNVBAYTA1VT ... 8I3bsbmRAUg4UP9hH6ABVq4KQKMknxu1xQxLhpR1y1GPdiowMNTrEG8cCx3w/w==</ds:X509Certificate> 
    </ds:X509Data> 
    </ds:KeyInfo> 
    </ds:Signature> 
</Assertion> 
</Response> 

Vậy làm cách nào để tạo một thứ như thế này? Và nếu tôi nhận được một cái gì đó như thế này, làm thế nào để tôi xác nhận nó? Ngoài ra, bất cứ ai cũng có thể cung cấp một cái nhìn khái niệm cơ bản về những gì các thẻ <ds:Signature> đang ở đây? Có vẻ như có hai thẻ <ds:Signature>, một trong số <Response> chính và một trong số <Assertion>, mỗi thẻ chứa <ds:DigestValue>, <ds:SignatureValue><ds:X509Certificate> (và mỗi khác biệt riêng). Chúng được tạo ra như thế nào? Bất kỳ ánh sáng bạn có thể đổ về điều này sẽ được nhiều đánh giá cao. Hướng dẫn hoặc ví dụ mã sẽ được đánh giá cao hơn nữa! Nhưng vào thời điểm này, nếu bạn có thể giúp tôi đi đúng hướng, đó là tất cả những gì tôi thực sự yêu cầu. Ngay bây giờ tất cả vẫn có vẻ giống như một chiếc hộp đen to với tôi. Bằng cách này, nếu điều này giúp, nó nói ở nơi khác trong thông số SAML 1.1 rằng việc triển khai SAML chỉ nên sử dụng phương pháp "Độc quyền Canonicalization" (Excl-C14N) và chỉ nên sử dụng "biến đổi bao bọc". Tôi vẫn chưa hoàn toàn chắc chắn điều đó có nghĩa là gì.

Trả lời

27

chữ ký Processing XML không thực sự là quá khó khăn, nếu bạn đang rất quen thuộc với XML, nhưng có rất nhiều chi tiết phải hoàn toàn đúng hoặc mọi thứ không hoạt động, vì vậy tôi có thể sẽ không cố gắng viết thực hiện của riêng mình trong tình huống này (tôi đã thực hiện nó một phần, nhưng đó là mục đích khác nhau và đặc biệt, và dù sao nó không phải là một triển khai hoàn chỉnh).

Dù sao, tôi không biết nhiều về SAML, nhưng tôi biết về XML và chữ ký XML, vì vậy có lẽ tôi có thể giúp bạn một số cách bằng cách cố gắng trả lời các câu hỏi của bạn.

Phần tử Signature đề cập đến một phần cụ thể của tài liệu XML đã được ký điện tử, trong phần tử con SignedInfo. Các yếu tố con Reference con đó (tôi nghĩ rằng có thể có nhiều yếu tố Reference được ghép khi tạo thành các byte được ký nhưng tôi không nhớ chắc chắn nữa) trỏ đến nội dung thông qua các thuộc tính URI. Các yếu tố Transform mô tả các phép biến đổi được thực hiện trên nội dung được gọi đến trước khi băm; bạn sẽ cần phải xem xét các thông số kỹ thuật để tìm ra cách các thuật toán chuyển đổi được xác định. Phần tử DigestMethod cung cấp thuật toán băm để áp dụng cho các byte là kết quả của các thuật toán chuyển đổi này (lưu ý rằng một trong số chúng luôn là chuẩn hóa chuyển đổi XML thành byte), và DigestValue cho kết quả của thuật toán phân loại đó.

Chữ ký thực tế nằm trong phần tử SignatureValue và được tạo bằng cách áp dụng quy tắc chuẩn hóa CanonicalizationMethod của phần tử để tạo các byte và sau đó ký các byte này với SignatureMethod. Phần tử KeyInfo cho bạn biết cách tìm chìa khóa để sử dụng.

Canonicalization, xuất hiện một vài lần ở trên, đơn giản chỉ là một cách để chuyển đổi tài liệu XML thành byte để các tài liệu XML "tương đương" tạo ra cùng một chuỗi byte. Điều này được yêu cầu trong một chữ ký số vì các thuật toán hoạt động trên các byte và XML có thể đi qua một số trung gian có thể sẽ làm gián đoạn các byte gốc nhưng sẽ giữ lại sự tương đương. Và các phương pháp chuẩn hóa khác nhau là cần thiết cho các tình huống khác nhau: nếu các phần tử được trích xuất từ ​​các tài liệu và được đặt vào các tài liệu khác, bạn cần phải chuẩn hóa độc quyền để loại bỏ các định nghĩa không gian tên không cần thiết, nhưng trong các trường hợp khác có thể không hoạt động chính xác. bảo toàn tất cả các không gian tên trong phạm vi.

Đây chỉ là vấn đề cơ bản. Có một số tùy chọn khác nhau về cách tạo ra một chữ ký XML, và nếu bạn muốn thực hiện một trình thẩm định làm việc, bạn cần phải xem xét tất cả chúng. Vì bạn mới sử dụng XML nói chung, tôi sẽ chỉ lặp lại lời khuyên của tôi về việc sử dụng cái gì đó đã tồn tại. Đó là một kinh nghiệm học tập thú vị để thực hiện một đặc điểm kỹ thuật, nhưng thường nó là một sự lãng phí thời gian nếu triển khai đã có sẵn.

+0

Khi bạn đã chỉ định ca thuật toán nonicalization trong phần tử phương thức chuẩn hóa của phần tử thông tin đã ký, tại sao bạn nên chỉ định nó một lần nữa trong phần tử transforms? – Ashwin

+1

@Ashwin: 'CanonicalizationMethod' trong' SignedInfo' là những gì được áp dụng cho phần tử 'SignedInfo', bất kỳ sự chuẩn hóa nào trong các biến đổi được áp dụng cho nội dung được giới thiệu, vì vậy chúng áp dụng cho những thứ khác nhau, và đó là lý do bạn cần cả hai. Ngoài ra, nội dung đã ký không cần phải là XML, vì vậy việc chuẩn hóa không nhất thiết phải áp dụng. – JaakkoK

+0

cảm ơn vì điều đó :) Có một khu vực nữa mà tôi bị kẹt ở đó. Tôi được yêu cầu sử dụng xslt trong phần tử biến đổi. Không có ví dụ về cách sử dụng nó trong java. Nếu có thể, bạn có thể đưa ra một mã mẫu hoặc chỉ ra một liên kết sử dụng xslt trong các chữ ký xml với java. – Ashwin

2

Có ví dụ trong xmlseclibs.php trong SimpleSAML. Nó dựa trên mô-đun openssl để làm mật mã.

tôi sẽ trung thực sử dụng lib hoặc cầu java/tomcat, chỉ vì vấn đề interop có thể đi lên rằng sẽ cần phải có khả năng được sửa lỗi,

Các vấn đề liên quan