Many people have asked how we can retrieve and process a token sent by a subject or a Security Token Service. Just to showcase the non-intrusiveness of _WCS_, in that we can easily incorporate a Cardspace "Sign-in with Cardspace" into your website today such as this or this, I have shown snippets of how we can do so via php here.
As an another example of non-intrusiveness, I have also got a simple working sample that you can use to integrate into your ASP.NET 2.0 page today.
Of course, this is a hack job and there are no try catch and the xml parsing code is hastily done. To summarize, I wont win the elegance award here ... but you can get it to work on .NET 2.0 (or maybe even 1.1) i-wink ...
Of course, this is a hack job and there are no try catch and the xml parsing code is hastily done. To summarize, I wont win the elegance award here ... but you can get it to work on .NET 2.0 (or maybe even 1.1) ...
[BEGIN]
'This will get you your encrypted token
Dim str As Stream
str = Request.InputStream
Dim sr As New StreamReader(str)
Dim s As String = sr.ReadToEnd
s = Server.HtmlDecode(Server.UrlDecode(s))
'the stream will be ASCII encoded
Dim u8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding
Dim fs As New FileStream("C:\temp\CardspaceXMLToken.xml", FileMode.Create)
'Remove the "xmlToken="
Dim i As Integer = s.IndexOf("<")
s = s.Substring(i)
fs.Write(u8.GetBytes(s), 0, u8.GetBytes(s).Length)
fs.Flush()
fs.Close()
'--------------------------------
'The will decrypt that request token and return a Signed Security SAML Token
Dim encryptedDoc As New XmlDocument()
encryptedDoc.Load("C:\temp\CardspaceXMLToken.xml")
'Check for <EncryptedData> element
If encryptedDoc.GetElementsByTagName _
("EncryptedData", "http://www.w3.org/2001/04/xmlenc#").Count = 0 Then Return
Dim encryptedD As XmlElement = CType(encryptedDoc.GetElementsByTagName _
("EncryptedData", "http://www.w3.org/2001/04/xmlenc#")(0), XmlElement)
'Check for @Algorithm attribute and make sure its http://www.w3.org/2001/04/xmlenc#aes256-cbc
If encryptedD.ChildNodes(0).Attributes("Algorithm") Is Nothing Or _
encryptedD.ChildNodes(0).Attributes("Algorithm").Value <> _
"http://www.w3.org/2001/04/xmlenc#aes256-cbc" Then Return
Dim a As New RijndaelManaged
'Check for <KeyInfo> element
If encryptedD.ChildNodes(1).Name <> "KeyInfo" Then Return
'Check for <EncryptionMethod> element
Dim encryptedM As XmlElement = CType(encryptedDoc.GetElementsByTagName _
("EncryptionMethod", "http://www.w3.org/2001/04/xmlenc#")(1), XmlElement)
'Check for @Algorithm attribute and make sure its http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p
If encryptedM.Attributes("Algorithm") Is Nothing Or _
encryptedM.Attributes("Algorithm").Value <> _
"http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" Then Return
'Check for <CipherData\CipherValue>
If encryptedD.GetElementsByTagName("CipherValue", _
"http://www.w3.org/2001/04/xmlenc#").Count = 0 Then Return
'Retrieving the Encrypted Symmetric Key and the Security Token
Dim e_SymmKey As String = encryptedDoc.GetElementsByTagName _
("CipherValue", "http://www.w3.org/2001/04/xmlenc#")(0).InnerText
Dim e_SecurityToken As String = encryptedDoc.GetElementsByTagName _
("CipherValue", "http://www.w3.org/2001/04/xmlenc#")(1).InnerText
Dim rsaCsp As New RSACryptoServiceProvider
Dim privatecert As New X509Certificates.X509Certificate2
privatecert.Import("Softwaremaker.NET.SSL.pfx", "Softwaremaker_NET_SSL_pfx_password", X509Certificates.X509KeyStorageFlags.Exportable)
rsaCsp.FromXmlString(privatecert.PrivateKey.ToXmlString(True))
'Now we have the Symmetric Key
Dim DecryptedStrAsByt() As Byte = _
rsaCsp.Decrypt(System.Convert.FromBase64String(e_SymmKey), True)
'Moving on to use the Symmetric Key to decrypt Token
Dim rijndaelM As New RijndaelManaged
rijndaelM.Mode = CipherMode.CBC
Dim swmDecryptor As ICryptoTransform
swmDecryptor = rijndaelM.CreateDecryptor(DecryptedStrAsByt, Nothing)
'Define memory stream which will be used to hold encrypted data.
Dim cipherTextBytes As Byte()
cipherTextBytes = System.Convert.FromBase64String(e_SecurityToken)
Dim memoryStream As MemoryStream
memoryStream = New MemoryStream(cipherTextBytes)
' Define memory stream which will be used to hold encrypted data.
Dim cryptoStream As CryptoStream
cryptoStream = New CryptoStream(memoryStream, swmDecryptor, CryptoStreamMode.Read)
' Since at this point we don't know what the size of decrypted data
' will be, allocate the buffer long enough to hold ciphertext;
' plaintext is never longer than ciphertext.
Dim plainTextBytes As Byte()
ReDim plainTextBytes(cipherTextBytes.Length)
' Start decrypting.
Dim decryptedByteCount As Integer
decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length)
' Close both streams.
memoryStream.Close()
cryptoStream.Close()
' Convert decrypted data into a string.
' Let us assume that the original plaintext string was UTF8-encoded.
Dim plainTextToken As String
plainTextToken = System.Text.Encoding.UTF8.GetString(plainTextBytes, 16, _
decryptedByteCount - 16)
return plainTextToken
[END]
'--------------------------------
Of course, you would have to verify the signed token yourself BUT this decryption process is definitely a step in the right direction
If you have benefitted from these sample snippets, maybe you can pay-it-forward by implementing and then sharing the signature-verification codes with me here? I am too lazy ... i-smile.