আমি মনে করি SecureString
নির্ভরশীল ফাংশনগুলির জন্য মেমরির ডিক্রিপ্টেড স্ট্রিংয়ের (আরও একবার পিন করা) ভাল নিয়ন্ত্রণের জন্য তাদের নির্ভর যুক্তিটিকে একটি অনামী কার্যক্রমে আবদ্ধ করা ভাল।
এই স্নিপেটে সিকিউরস্ট্রিংগুলি ডিক্রিপ্ট করার জন্য প্রয়োগটি হবে:
- স্মৃতিতে স্ট্রিংটি পিন করুন (যা আপনি করতে চান তবে বেশিরভাগ উত্তর থেকে এখানে অনুপস্থিত বলে মনে হচ্ছে)।
- এর রেফারেন্সটি ফানক / অ্যাকশন প্রতিনিধিটির কাছে পাস করুন ।
- এটিকে মেমরি থেকে স্ক্রাব করুন এবং
finally
ব্লকটিতে জিসিকে ছেড়ে দিন ।
এটি স্পষ্টতই "স্ট্যান্ডার্ডাইজড" করা এবং কলার বনাম বজায় রাখতে খুব সহজ করে তোলে যার চেয়ে কম পছন্দসই বিকল্পগুলির উপর নির্ভর করে:
- কোনও
string DecryptSecureString(...)
সহায়ক ফাংশন থেকে ডিক্রিপ্ট করা স্ট্রিংটি ফিরিয়ে দেওয়া ।
- এই কোডটি যেখানেই প্রয়োজন সেখানে সদৃশ।
এখানে লক্ষ্য করুন, আপনার দুটি বিকল্প রয়েছে:
static T DecryptSecureString<T>
যা আপনাকে Func
কলারের কাছ থেকে প্রতিনিধিটির ফলাফল অ্যাক্সেস করতে দেয় ( DecryptSecureStringWithFunc
পরীক্ষার পদ্ধতিতে দেখানো হয়েছে )।
static void DecryptSecureString
কেবলমাত্র একটি "অকার্যকর" সংস্করণ যা কোনও Action
প্রতিনিধি নিয়োগ করে যেখানে আপনি আসলে কিছু চান না / ফিরিয়ে দিতে চান না ( DecryptSecureStringWithAction
পরীক্ষার পদ্ধতিতে প্রদর্শিত হিসাবে )।
উভয়ের জন্য উদাহরণের ব্যবহার StringsTest
অন্তর্ভুক্ত শ্রেণিতে পাওয়া যাবে ।
Strings.cs
using System;
using System.Runtime.InteropServices;
using System.Security;
namespace SecurityUtils
{
public partial class Strings
{
/// <summary>
/// Passes decrypted password String pinned in memory to Func delegate scrubbed on return.
/// </summary>
/// <typeparam name="T">Generic type returned by Func delegate</typeparam>
/// <param name="action">Func delegate which will receive the decrypted password pinned in memory as a String object</param>
/// <returns>Result of Func delegate</returns>
public static T DecryptSecureString<T>(SecureString secureString, Func<string, T> action)
{
var insecureStringPointer = IntPtr.Zero;
var insecureString = String.Empty;
var gcHandler = GCHandle.Alloc(insecureString, GCHandleType.Pinned);
try
{
insecureStringPointer = Marshal.SecureStringToGlobalAllocUnicode(secureString);
insecureString = Marshal.PtrToStringUni(insecureStringPointer);
return action(insecureString);
}
finally
{
//clear memory immediately - don't wait for garbage collector
fixed(char* ptr = insecureString )
{
for(int i = 0; i < insecureString.Length; i++)
{
ptr[i] = '\0';
}
}
insecureString = null;
gcHandler.Free();
Marshal.ZeroFreeGlobalAllocUnicode(insecureStringPointer);
}
}
/// <summary>
/// Runs DecryptSecureString with support for Action to leverage void return type
/// </summary>
/// <param name="secureString"></param>
/// <param name="action"></param>
public static void DecryptSecureString(SecureString secureString, Action<string> action)
{
DecryptSecureString<int>(secureString, (s) =>
{
action(s);
return 0;
});
}
}
}
StringsTest.cs
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Security;
namespace SecurityUtils.Test
{
[TestClass]
public class StringsTest
{
[TestMethod]
public void DecryptSecureStringWithFunc()
{
// Arrange
var secureString = new SecureString();
foreach (var c in "UserPassword123".ToCharArray())
secureString.AppendChar(c);
secureString.MakeReadOnly();
// Act
var result = Strings.DecryptSecureString<bool>(secureString, (password) =>
{
return password.Equals("UserPassword123");
});
// Assert
Assert.IsTrue(result);
}
[TestMethod]
public void DecryptSecureStringWithAction()
{
// Arrange
var secureString = new SecureString();
foreach (var c in "UserPassword123".ToCharArray())
secureString.AppendChar(c);
secureString.MakeReadOnly();
// Act
var result = false;
Strings.DecryptSecureString(secureString, (password) =>
{
result = password.Equals("UserPassword123");
});
// Assert
Assert.IsTrue(result);
}
}
}
স্পষ্টতই, এটি নিম্নলিখিত পদ্ধতিতে এই ফাংশনটির অপব্যবহার রোধ করে না, তাই এটি না করার জন্য কেবল সাবধান হন:
[TestMethod]
public void DecryptSecureStringWithAction()
{
// Arrange
var secureString = new SecureString();
foreach (var c in "UserPassword123".ToCharArray())
secureString.AppendChar(c);
secureString.MakeReadOnly();
// Act
string copyPassword = null;
Strings.DecryptSecureString(secureString, (password) =>
{
copyPassword = password; // Please don't do this!
});
// Assert
Assert.IsNull(copyPassword); // Fails
}
শুভ কোডিং!