diff --git a/src/Agent.Listener/Configuration.Windows/RSAEncryptedFileKeyManager.cs b/src/Agent.Listener/Configuration.Windows/RSAEncryptedFileKeyManager.cs
index a64c9d3c2b..2bbcd7cf06 100644
--- a/src/Agent.Listener/Configuration.Windows/RSAEncryptedFileKeyManager.cs
+++ b/src/Agent.Listener/Configuration.Windows/RSAEncryptedFileKeyManager.cs
@@ -132,12 +132,12 @@ public void DeleteKey()
}
}
- public RSA GetKey()
+ public RSA GetKey(bool useLegacyRsaImpl)
{
- return GetKeyFromFile();
+ return GetKeyFromFile(useLegacyRsaImpl);
}
- private RSA GetKeyFromNamedContainer()
+ private RSA GetKeyFromNamedContainer(bool useLegacyRsaImpl)
{
if (!File.Exists(_keyFile))
{
@@ -151,7 +151,7 @@ private RSA GetKeyFromNamedContainer()
if (string.IsNullOrEmpty(result.containerName))
{
// we should not get here. GetKeyFromNamedContainer is only called from GetKeyFromFile when result.containerName is not empty
- return GetKeyFromFile();
+ return GetKeyFromFile(useLegacyRsaImpl);
}
if (result.useCng)
@@ -170,13 +170,24 @@ private RSA GetKeyFromNamedContainer()
Trace.Info("Using RSACryptoServiceProvider");
CspParameters Params = new CspParameters();
Params.KeyContainerName = result.containerName;
- Params.Flags |= CspProviderFlags.UseNonExportableKey | CspProviderFlags.UseMachineKeyStore;
- var rsa = new RSACryptoServiceProvider(Params);
- return rsa;
+ if (useLegacyRsaImpl)
+ {
+ Params.Flags |= CspProviderFlags.UseNonExportableKey | CspProviderFlags.UseMachineKeyStore;
+ var rsa = new RSACryptoServiceProvider(Params);
+ return rsa;
+ }
+ else
+ {
+ Params.Flags |= CspProviderFlags.UseMachineKeyStore;
+ using (var csp = new RSACryptoServiceProvider(Params))
+ {
+ return RSA.Create(csp.ExportParameters(includePrivateParameters: true));
+ }
+ }
}
}
- private RSA GetKeyFromFile()
+ private RSA GetKeyFromFile(bool useLegacyRsaImpl)
{
if (!File.Exists(_keyFile))
{
@@ -190,10 +201,10 @@ private RSA GetKeyFromFile()
if(!string.IsNullOrEmpty(result.containerName))
{
Trace.Info("Keyfile has ContainerName, reading from NamedContainer");
- return GetKeyFromNamedContainer();
+ return GetKeyFromNamedContainer(useLegacyRsaImpl);
}
- var rsa = new RSACryptoServiceProvider();
+ var rsa = useLegacyRsaImpl ? new RSACryptoServiceProvider() : RSA.Create();
rsa.ImportParameters(result.rsaParameters);
return rsa;
}
diff --git a/src/Agent.Listener/Configuration/IRSAKeyManager.cs b/src/Agent.Listener/Configuration/IRSAKeyManager.cs
index f6f5dce38e..9f259a8181 100644
--- a/src/Agent.Listener/Configuration/IRSAKeyManager.cs
+++ b/src/Agent.Listener/Configuration/IRSAKeyManager.cs
@@ -35,11 +35,12 @@ public interface IRSAKeyManager : IAgentService
void DeleteKey();
///
- /// Gets the RSACryptoServiceProvider instance currently stored by the key manager.
+ /// Gets the RSA instance currently stored by the key manager.
///
- /// An RSACryptoServiceProvider instance representing the key for the agent
+ /// Use RSACryptoServiceProvider as the underlying implementation.
+ /// An RSA implementation representing the key for the agent
/// No key exists in the store
- RSA GetKey();
+ RSA GetKey(bool useLegacyRsaImpl);
}
public static class IRSAKeyManagerExtensions
diff --git a/src/Agent.Listener/Configuration/OAuthCredential.cs b/src/Agent.Listener/Configuration/OAuthCredential.cs
index 82dc71780c..86b5c36848 100644
--- a/src/Agent.Listener/Configuration/OAuthCredential.cs
+++ b/src/Agent.Listener/Configuration/OAuthCredential.cs
@@ -42,7 +42,7 @@ public override VssCredentials GetVssCredentials(IHostContext context)
// We expect the key to be in the machine store at this point. Configuration should have set all of
// this up correctly so we can use the key to generate access tokens.
var keyManager = context.GetService();
- var signingCredentials = VssSigningCredentials.Create(() => keyManager.GetKey());
+ var signingCredentials = VssSigningCredentials.Create(() => keyManager.GetKey(useLegacyRsaImpl: true)); // RSACryptoServiceProvider is fine for signatures
var clientCredential = new VssOAuthJwtBearerClientCredential(clientId, authorizationUrl, signingCredentials);
var agentCredential = new VssOAuthCredential(new Uri(oathEndpointUrl, UriKind.Absolute), VssOAuthGrant.ClientCredentials, clientCredential);
diff --git a/src/Agent.Listener/Configuration/RSAFileKeyManager.cs b/src/Agent.Listener/Configuration/RSAFileKeyManager.cs
index 03d1fe43bf..f9a3830236 100644
--- a/src/Agent.Listener/Configuration/RSAFileKeyManager.cs
+++ b/src/Agent.Listener/Configuration/RSAFileKeyManager.cs
@@ -70,7 +70,7 @@ public void DeleteKey()
}
}
- public RSA GetKey()
+ public RSA GetKey(bool useLegacyRsaImpl)
{
if (!File.Exists(_keyFile))
{
@@ -80,7 +80,7 @@ public RSA GetKey()
Trace.Info("Loading RSA key parameters from file {0}", _keyFile);
var parameters = IOUtil.LoadObject(_keyFile).RSAParameters;
- var rsa = new RSACryptoServiceProvider();
+ var rsa = useLegacyRsaImpl ? new RSACryptoServiceProvider() : RSA.Create();
rsa.ImportParameters(parameters);
return rsa;
}
diff --git a/src/Agent.Listener/MessageListener.cs b/src/Agent.Listener/MessageListener.cs
index eebca9d1f7..d3900a8402 100644
--- a/src/Agent.Listener/MessageListener.cs
+++ b/src/Agent.Listener/MessageListener.cs
@@ -95,6 +95,7 @@ public async Task CreateSessionAsync(CancellationToken token)
await _agentServer.ConnectAsync(new Uri(serverUrl), creds);
Trace.Info("VssConnection created");
+ taskAgentSession.AgentCanHandleOaepSHA256 = true;
_session = await _agentServer.CreateAgentSessionAsync(
_settings.PoolId,
taskAgentSession,
@@ -336,9 +337,10 @@ private ICryptoTransform GetMessageDecryptor(
{
// The agent session encryption key uses the AES symmetric algorithm
var keyManager = HostContext.GetService();
- using (var rsa = keyManager.GetKey())
+ RSAEncryptionPadding rsaPadding = _session.EncryptionKey.EncryptionPadding == "OaepSHA256" ? RSAEncryptionPadding.OaepSHA256 : RSAEncryptionPadding.OaepSHA1;
+ using (var rsa = keyManager.GetKey(useLegacyRsaImpl: rsaPadding == RSAEncryptionPadding.OaepSHA1))
{
- return aes.CreateDecryptor(rsa.Decrypt(_session.EncryptionKey.Value, RSAEncryptionPadding.OaepSHA1), message.IV);
+ return aes.CreateDecryptor(rsa.Decrypt(_session.EncryptionKey.Value, rsaPadding), message.IV);
}
}
else