Skip to content

Commit

Permalink
core: remove legacy cryptographic code. #10433 (#10477)
Browse files Browse the repository at this point in the history
Legacy code was deprecated on May 30, 2018
e73ae99
  • Loading branch information
ngosang committed Dec 12, 2020
1 parent ce4b993 commit 0e12f35
Show file tree
Hide file tree
Showing 3 changed files with 6 additions and 196 deletions.
22 changes: 0 additions & 22 deletions src/Jackett.Common/Indexers/BaseIndexer.cs
Expand Up @@ -220,29 +220,7 @@ private bool MigratedFromDPAPI(JToken jsonConfig)
catch (Exception ex)
{
if (ex.Message != "The provided payload cannot be decrypted because it was not protected with this protection provider.")
{
logger.Info($"Password could not be unprotected using Microsoft.AspNetCore.DataProtection - {Id} : " + ex);
}

logger.Info($"Attempting legacy Unprotect - {Id} : ");

try
{
var unprotectedPassword = protectionService.LegacyUnProtect(passwordValue);
//Password successfully unprotected using Windows/Mono DPAPI

passwordPropertyValue.Value = unprotectedPassword;
SaveConfig();
IsConfigured = true;

logger.Info($"Password successfully migrated for {Id}");

return true;
}
catch (Exception exception)
{
logger.Info($"Password could not be unprotected using legacy DPAPI - {Id} : " + exception);
}
}
}

Expand Down
2 changes: 0 additions & 2 deletions src/Jackett.Common/Services/Interfaces/IProtectionService.cs
Expand Up @@ -4,7 +4,5 @@ public interface IProtectionService
{
string Protect(string plainText);
string UnProtect(string plainText);
string LegacyProtect(string plainText);
string LegacyUnProtect(string plainText);
}
}
178 changes: 6 additions & 172 deletions src/Jackett.Server/Services/ProtectionService.cs
@@ -1,43 +1,24 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using Jackett.Common;
using Jackett.Common.Models.Config;
using Jackett.Common.Services.Interfaces;
using Jackett.Common.Utils;
using Microsoft.AspNetCore.DataProtection;

namespace Jackett.Server.Services
{

public class ProtectionService : IProtectionService
{
private readonly DataProtectionScope PROTECTION_SCOPE = DataProtectionScope.LocalMachine;
private const string JACKETT_KEY = "JACKETT_KEY";
private const string APPLICATION_KEY = "Dvz66r3n8vhTGip2/quiw5ISyM37f7L2iOdupzdKmzkvXGhAgQiWK+6F+4qpxjPVNks1qO7LdWuVqRlzgLzeW8mChC6JnBMUS1Fin4N2nS9lh4XPuCZ1che75xO92Nk2vyXUo9KSFG1hvEszAuLfG2Mcg1r0sVyVXd2gQDU/TbY=";
private readonly byte[] _instanceKey;
private readonly IDataProtector _protector = null;
private const string JackettKey = "JACKETT_KEY";
private const string ApplicationKey = "Dvz66r3n8vhTGip2/quiw5ISyM37f7L2iOdupzdKmzkvXGhAgQiWK+6F+4qpxjPVNks1qO7LdWuVqRlzgLzeW8mChC6JnBMUS1Fin4N2nS9lh4XPuCZ1che75xO92Nk2vyXUo9KSFG1hvEszAuLfG2Mcg1r0sVyVXd2gQDU/TbY=";
private readonly IDataProtector _protector;

public ProtectionService(ServerConfig config, IDataProtectionProvider provider = null)
public ProtectionService(IDataProtectionProvider provider = null)
{
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
// We should not be running as root and will only have access to the local store.
PROTECTION_SCOPE = DataProtectionScope.CurrentUser;
}
_instanceKey = Encoding.UTF8.GetBytes(config.InstanceId);

if (provider != null)
{
var jackettKey = Environment.GetEnvironmentVariable(JACKETT_KEY);
var purpose = string.IsNullOrEmpty(jackettKey) ? APPLICATION_KEY : jackettKey.ToString();
var jackettKey = Environment.GetEnvironmentVariable(JackettKey);
var purpose = string.IsNullOrEmpty(jackettKey) ? ApplicationKey : jackettKey;

_protector = provider.CreateProtector(purpose);
}

}

public string Protect(string plainText)
Expand All @@ -55,152 +36,5 @@ public string UnProtect(string plainText)

return _protector.Unprotect(plainText);
}

public string LegacyProtect(string plainText)
{
var jackettKey = Environment.GetEnvironmentVariable(JACKETT_KEY);

if (jackettKey == null)
{
return ProtectDefaultMethod(plainText);
}
else
{
return ProtectUsingKey(plainText, jackettKey);
}
}

public string LegacyUnProtect(string plainText)
{
var jackettKey = Environment.GetEnvironmentVariable(JACKETT_KEY);

if (jackettKey == null)
{
return UnProtectDefaultMethod(plainText);
}
else
{
return UnProtectUsingKey(plainText, jackettKey);
}
}

private string ProtectDefaultMethod(string plainText)
{
if (string.IsNullOrEmpty(plainText))
return string.Empty;

var plainBytes = Encoding.UTF8.GetBytes(plainText);
var appKey = Convert.FromBase64String(APPLICATION_KEY);
var instanceKey = _instanceKey;
var entropy = new byte[appKey.Length + instanceKey.Length];
Buffer.BlockCopy(instanceKey, 0, entropy, 0, instanceKey.Length);
Buffer.BlockCopy(appKey, 0, entropy, instanceKey.Length, appKey.Length);

var protectedBytes = ProtectedData.Protect(plainBytes, entropy, PROTECTION_SCOPE);

using (var ms = new MemoryStream())
{
using (var AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;

var key = new Rfc2898DeriveBytes(instanceKey, instanceKey.Reverse().ToArray(), 64);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);

AES.Mode = CipherMode.CBC;

using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(protectedBytes, 0, protectedBytes.Length);
cs.Close();
}
protectedBytes = ms.ToArray();
}
}

return Convert.ToBase64String(protectedBytes);
}

private string UnProtectDefaultMethod(string plainText)
{
if (string.IsNullOrEmpty(plainText))
return string.Empty;

var protectedBytes = Convert.FromBase64String(plainText);
var instanceKey = _instanceKey;

using (var ms = new MemoryStream())
{
using (var AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;

var key = new Rfc2898DeriveBytes(instanceKey, instanceKey.Reverse().ToArray(), 64);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);

AES.Mode = CipherMode.CBC;

using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(protectedBytes, 0, protectedBytes.Length);
cs.Close();
}
protectedBytes = ms.ToArray();
}
}

var appKey = Convert.FromBase64String(APPLICATION_KEY);
var entropy = new byte[appKey.Length + instanceKey.Length];
Buffer.BlockCopy(instanceKey, 0, entropy, 0, instanceKey.Length);
Buffer.BlockCopy(appKey, 0, entropy, instanceKey.Length, appKey.Length);

var unprotectedBytes = ProtectedData.Unprotect(protectedBytes, entropy, PROTECTION_SCOPE);
return Encoding.UTF8.GetString(unprotectedBytes);
}

private string ProtectUsingKey(string plainText, string key) => StringCipher.Encrypt(plainText, key);

private string UnProtectUsingKey(string plainText, string key) => StringCipher.Decrypt(plainText, key);

// Currently unused
public void Protect<T>(T obj)
{
var type = obj.GetType();

foreach (var property in type.GetProperties(BindingFlags.SetProperty | BindingFlags.GetProperty | BindingFlags.Public))
{
if (property.GetCustomAttributes(typeof(JackettProtectedAttribute), false).Count() > 0)
{
var value = property.GetValue(obj);
if (value is string)
{
var protectedString = Protect(value as string);
property.SetValue(obj, protectedString);
}
}
}
}

public void UnProtect<T>(T obj)
{
var type = obj.GetType();

foreach (var property in type.GetProperties(BindingFlags.SetProperty | BindingFlags.GetProperty | BindingFlags.Public))
{
if (property.GetCustomAttributes(typeof(JackettProtectedAttribute), false).Count() > 0)
{
var value = property.GetValue(obj);
if (value is string)
{
var unprotectedString = UnProtect(value as string);
property.SetValue(obj, unprotectedString);
}
}
}
}
}
}

0 comments on commit 0e12f35

Please sign in to comment.