Using IdentityModel: Simplifying Calculation of Information Card Unique IDs in WCF
The key to information card backed systems is calculating a stable unique identifier for your users based on the card claims. Typically this is done by hashing the issuer public key (plus some other information like a PPID for managed cards). This involves the following steps: - Find the issuer claim set containing the issuer RSA key
- Optionally find some other claims (e.g. a PPID)
- Create a hash from that pieces of information
In LeastPrivilege.IdentityModel I added some helper extension methods to simplify this process. The first one extends the RSACryptoServiceProvider class and allows calculating the hash the from the key (plus optional extra information): public static class RSAExtensions { public static byte[] GetKeyHash(this RSACryptoServiceProvider rsa) { return rsa.GetKeyHash(string.Empty); }
public static byte[] GetKeyHash(this RSACryptoServiceProvider rsa, string entropy) { int entropyLength = Encoding.UTF8.GetByteCount(entropy); RSAParameters rsaParams = rsa.ExportParameters(false); byte[] shaInput; byte[] shaOutput;
int i = 0; shaInput = new byte[rsaParams.Modulus.Length + rsaParams.Exponent.Length + entropyLength]; rsaParams.Modulus.CopyTo(shaInput, i); i += rsaParams.Modulus.Length; rsaParams.Exponent.CopyTo(shaInput, i); i += rsaParams.Exponent.Length; i += Encoding.UTF8.GetBytes(entropy, 0, entropy.Length, shaInput, i);
using (SHA256 sha = SHA256.Create()) { shaOutput = sha.ComputeHash(shaInput); }
return shaOutput; } } I use the same algorithm here as in Microsoft's Token class for ASP.NET. This makes it easy to share the IDs between ASP.NET and other application types. Another helper extends IEnumerable<ClaimSet> and simplifies retrieving the RSA claim: public static RSACryptoServiceProvider FindIssuerRsaClaim( this IEnumerable<ClaimSet> claimSets) { return claimSets.FindClaim( ClaimTypes.Rsa, ClaimSearchMode.Issuer).Get<RSACryptoServiceProvider>(); } With these helpers you can retrieve the unique ID by using this code: AuthorizationContext context = ServiceSecurityContext.Current.AuthorizationContext; byte[] uniqueId = context.ClaimSets.FindIssuerRsaClaim().GetKeyHash(); IdentityModel | WCF
Tuesday, March 04, 2008 12:26:35 AM UTC
|