Skip to content

Commit c4c928b

Browse files
committed
Support SAML2 EncryptedAssertion WriteToken
* Set EncryptingCredentials to Saml2Assertion when creating a saml2 token * Add support classes for SAML2 Encryption - TODO comments and xml read/write implementation * Cover encryption with pre-shared session key # Conflicts: # src/Microsoft.IdentityModel.Tokens.Saml/Saml2/Saml2Assertion.cs # src/Microsoft.IdentityModel.Tokens.Saml/Saml2/Saml2Serializer.cs # src/Microsoft.IdentityModel.Tokens/Encryption/AuthenticatedEncryptionProvider.cs # src/Microsoft.IdentityModel.Tokens/Utility.cs
1 parent 145473f commit c4c928b

File tree

8 files changed

+34
-22
lines changed

8 files changed

+34
-22
lines changed

build/targets.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project>
22
<PropertyGroup>
3-
<SrcTargets>net45;net461;netstandard2.0</SrcTargets>
3+
<SrcTargets>net45;net461;netstandard2.0;netstandard2.1</SrcTargets>
44
<SrcStandardTargets>netstandard2.0</SrcStandardTargets>
55
</PropertyGroup>
66
</Project>

src/Microsoft.IdentityModel.Tokens.Saml/Saml/SamlSecurityTokenHandler.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,7 @@ public override bool CanReadToken(string securityToken)
157157
#if NET45
158158
settings.XmlResolver = null;
159159
#endif
160-
using (var reader = XmlDictionaryReader.CreateDictionaryReader(XmlReader.Create(sr, settings)))
161-
{
162-
return CanReadToken(reader);
163-
}
160+
return CanReadToken(reader);
164161
}
165162
}
166163
catch (Exception)

src/Microsoft.IdentityModel.Tokens.Saml/Saml2/Saml2Assertion.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ internal string CanonicalString
158158
}
159159
}
160160

161+
/// <summary>
161162
/// Gets or sets the credentials used for encrypting the assertion.
162163
/// </summary>
163164
/// <exception cref="Saml2SecurityTokenEncryptedAssertionException"> If this assertion is encrypted.</exception>

src/Microsoft.IdentityModel.Tokens.Saml/Saml2/Saml2SecurityTokenHandler.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,7 @@ public override bool CanReadToken(string token)
106106
#if NET45
107107
settings.XmlResolver = null;
108108
#endif
109-
using (var reader = XmlDictionaryReader.CreateDictionaryReader(XmlReader.Create(sr, settings)))
110-
{
111-
return CanReadToken(reader);
112-
}
109+
return CanReadToken(reader);
113110
}
114111
}
115112
catch(Exception )

src/Microsoft.IdentityModel.Tokens.Saml/Saml2/Saml2Serializer.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ public class Saml2Serializer
4545
private string _prefix = Saml2Constants.Prefix;
4646
private readonly IEncryptedAssertionHandler _encryptedAssertionHandler;
4747

48+
/// <summary>
49+
/// Instantiates a new instance of <see cref="Saml2Serializer"/>.
50+
/// </summary>
51+
public Saml2Serializer()
52+
{
53+
_encryptedAssertionHandler = null;
54+
}
55+
4856
/// <summary>
4957
/// Instantiates a new instance of <see cref="Saml2Serializer"/>.
5058
/// </summary>

src/Microsoft.IdentityModel.Tokens/Encryption/AuthenticatedEncryptionProvider.cs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,10 @@ namespace Microsoft.IdentityModel.Tokens
3737
/// </summary>
3838
public class AuthenticatedEncryptionProvider : IDisposable
3939
{
40+
#if NETSTANDARD2_1
4041
private const int AES_GCM_IV_SIZE = 12;
4142
private const int AES_GCM_TAG_SIZE = 16;
42-
43+
#endif
4344
private struct AuthenticatedKeys
4445
{
4546
public SymmetricSecurityKey AesKey;
@@ -148,39 +149,42 @@ public virtual AuthenticatedEncryptionResult Encrypt(byte[] plaintext, byte[] au
148149
if (_disposed)
149150
throw LogHelper.LogExceptionMessage(new ObjectDisposedException(GetType().ToString()));
150151

152+
byte[] ciphertext;
153+
154+
#if NETSTANDARD2_1
151155
if (IsAesGcmAlgorithm(Algorithm))
152156
{
153-
byte[] ciphertext = new byte[plaintext.Length];
157+
ciphertext = new byte[plaintext.Length];
154158
byte[] nonce = new byte[AES_GCM_IV_SIZE];
155159
byte[] tag = new byte[AES_GCM_TAG_SIZE];
156-
157160
using (var aesGcm = new AesGcm(GetKeyBytes(Key)))
158161
{
159162
//random nonce
160163
RandomNumberGenerator rng = RandomNumberGenerator.Create();
161164
rng.GetBytes(nonce);
165+
162166
try
163-
- {
167+
{
164168
aesGcm.Encrypt(nonce, plaintext, ciphertext, tag);
165169
}
166-
catch (Exception ex)
167-
- {
170+
catch(Exception ex)
171+
{
168172
throw LogHelper.LogExceptionMessage(new SecurityTokenEncryptionFailedException(LogHelper.FormatInvariant(LogMessages.IDX10618, Algorithm), ex));
169173
}
170174
}
171175

172176
return new AuthenticatedEncryptionResult(Key, ciphertext, nonce, tag);
173177
}
174178
else
175-
{
179+
{
180+
#endif
176181
Aes aes = Aes.Create();
177182
aes.Mode = CipherMode.CBC;
178183
aes.Padding = PaddingMode.PKCS7;
179184
aes.Key = _authenticatedkeys.AesKey.Key;
180185
if (iv != null)
181186
aes.IV = iv;
182187

183-
byte[] ciphertext;
184188
try
185189
{
186190
ciphertext = Transform(aes.CreateEncryptor(), plaintext, 0, plaintext.Length);
@@ -201,8 +205,10 @@ public virtual AuthenticatedEncryptionResult Encrypt(byte[] plaintext, byte[] au
201205
Array.Copy(macHash, authenticationTag, authenticationTag.Length);
202206

203207
return new AuthenticatedEncryptionResult(Key, ciphertext, aes.IV, authenticationTag);
208+
#if NETSTANDARD2_1
209+
}
210+
#endif
204211
}
205-
}
206212

207213
/// <summary>
208214
/// Decrypts ciphertext into plaintext

src/Microsoft.IdentityModel.Tokens/LogMessages.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ internal static class LogMessages
123123
public const string IDX10616 = "IDX10616: Encryption failed. EncryptionProvider failed for: Algorithm: '{0}', SecurityKey: '{1}'. See inner exception.";
124124
public const string IDX10617 = "IDX10617: Encryption failed. Keywrap is only supported for: '{0}', '{1}' and '{2}'. The content encryption specified is: '{3}'.";
125125
public const string IDX10618 = "IDX10618: Encryption failed. EncryptionProvider failed for: Algorithm: '{0}'. See inner exception.";
126-
public const string IDX10619 = "IDX10619: Decryption failed. EncryptionProvider failed for: Algorithm: '{0}'. See inner exception.";
127-
public const string IDX10620 = "IDX10620: Decryption failed. Cipher-text size is less than 1.";
126+
//public const string IDX10619 = "IDX10619: Decryption failed. EncryptionProvider failed for: Algorithm: '{0}'. See inner exception.";
127+
//public const string IDX10620 = "IDX10620: Decryption failed. Cipher-text size is less than 1.";
128128

129129
// Formating
130130
public const string IDX10400 = "IDX10400: Unable to decode: '{0}' as Base64url encoded string.";

test/Microsoft.IdentityModel.Tokens.Saml.Tests/Helpers/AesGcmAuthenticatedEncryptionProvider.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131

3232
namespace Microsoft.IdentityModel.Tokens.Saml.Tests
3333
{
34+
35+
#if FALSE
3436
// Helper AuthenticatedEncryptionProvider class made to mimic AES-GCM
3537
// remove when AES-GCM is released and supported
3638
public class AesGcmAuthenticatedEncryptionProvider : AuthenticatedEncryptionProvider
@@ -69,7 +71,7 @@ public override AuthenticatedEncryptionResult Encrypt(byte[] plaintext, byte[] a
6971
}
7072
catch (Exception ex)
7173
{
72-
throw LogHelper.LogExceptionMessage(new SecurityTokenEncryptionFailedException(LogHelper.FormatInvariant(Tokens.LogMessages.IDX10618, Algorithm), ex));
74+
throw LogHelper.LogExceptionMessage(new SecurityTokenEncryptionFailedException(LogHelper.FormatInvariant("Tokens.LogMessages.IDX10618", Algorithm), ex));
7375
}
7476
}
7577

@@ -87,7 +89,7 @@ public override byte[] Decrypt(byte[] ciphertext, byte[] authenticatedData, byte
8789
int cipherSize = ciphertext.Length - AES_GCM_IV_SIZE - AES_GCM_TAG_SIZE;
8890

8991
if (cipherSize < 1)
90-
throw LogHelper.LogExceptionMessage(new SecurityTokenDecryptionFailedException(LogHelper.FormatInvariant(Tokens.LogMessages.IDX10620)));
92+
throw LogHelper.LogExceptionMessage(new SecurityTokenDecryptionFailedException(LogHelper.FormatInvariant("Tokens.LogMessages.IDX10620")));
9193

9294
byte[] cipher = new byte[cipherSize];
9395
byte[] nonce = new byte[AES_GCM_IV_SIZE];
@@ -156,4 +158,5 @@ public void Decrypt(byte[] nonce, byte[] ciphertext, byte[] tag, byte[] plaintex
156158
Array.Copy(ciphertext, plaintext, ciphertext.Length);
157159
}
158160
}
161+
#endif
159162
}

0 commit comments

Comments
 (0)