সিকিউরস্ট্রিংকে সিস্টেম.স্ট্রিংয়ে কীভাবে রূপান্তর করবেন?


156

একটি System.String আউট এটি তৈরি করে আপনার SecureString unsecuring সম্পর্কে সবকিছু রিজার্ভেশন সরাইয়া যে, তা কিভাবে করা যেতে পারে?

আমি কীভাবে একটি সাধারণ সিস্টেম.সিকিউরিটি.সিকিউরস্ট্রিংকে সিস্টেম.স্ট্রিংয়ে রূপান্তর করতে পারি?

আমি নিশ্চিত যে সিকিউরস্ট্রিংয়ের সাথে পরিচিত আপনারা অনেকেই প্রতিক্রিয়া জানাতে চলেছেন যে সিকিউরস্ট্রিংকে কখনই কোনও সাধারণ .NET স্ট্রিংতে রূপান্তর করা উচিত নয় কারণ এটি সমস্ত সুরক্ষা সুরক্ষা অপসারণ করে। আমি জানি । তবে এই মুহুর্তে আমার প্রোগ্রামটি সাধারণ স্ট্রিংয়ের সাথে সবকিছুই করেছে এবং আমি এটির সুরক্ষা বাড়ানোর চেষ্টা করছি এবং যদিও আমি এমন একটি এপিআই ব্যবহার করব যা আমার কাছে একটি সিকিউরস্ট্রিং ফিরিয়ে দেয় আমি সেটিকে আমার সুরক্ষা বাড়ানোর জন্য ব্যবহার করার চেষ্টা করছি না

আমি মার্শাল.সিকিউরস্ট্রিং টোবিএসটিআর সম্পর্কে সচেতন, কিন্তু কীভাবে এই বিএসটিআর নিতে হয় এবং একটি সিস্টেম তৈরি করতে হয় তা আমি জানি না it এটিকে বাইরে রেখে।

যারা আমার কাছে কেন এটি করতে চান তা জানতে চাইতে পারে, ভাল, আমি কোনও ব্যবহারকারীর কাছ থেকে একটি পাসওয়ার্ড নিচ্ছি এবং ব্যবহারকারীকে কোনও ওয়েবসাইটে লগ ইন করার জন্য এটি একটি এইচটিএমএল ফর্ম পোস্ট হিসাবে জমা দিচ্ছি। সুতরাং ... এটি সত্যিই পরিচালিত, এনক্রিপ্ট করা বাফারগুলির সাথে সম্পন্ন করতে হবে। যদি আমি এমনকি ব্যবস্থাবিহীন, এনক্রিপ্ট না করা বাফার অ্যাক্সেস পেতে পারি তবে আমি কল্পনা করেছিলাম যে আমি নেটওয়ার্ক স্ট্রিমে বাই-বাই-বাইট স্ট্রিম লিখন করতে পারি এবং আশা করি পাসওয়ার্ডটি পুরোপুরি সুরক্ষিত রাখবে। আমি এই পরিস্থিতিতে অন্তত একটি উত্তর উত্তর আশা করছি।

উত্তর:


192

System.Runtime.InteropServices.Marshalক্লাসটি ব্যবহার করুন :

String SecureStringToString(SecureString value) {
  IntPtr valuePtr = IntPtr.Zero;
  try {
    valuePtr = Marshal.SecureStringToGlobalAllocUnicode(value);
    return Marshal.PtrToStringUni(valuePtr);
  } finally {
    Marshal.ZeroFreeGlobalAllocUnicode(valuePtr);
  }
}

আপনি যদি কোনও পরিচালিত স্ট্রিং অবজেক্ট তৈরি করা এড়াতে চান তবে আপনি কাঁচা ডেটা ব্যবহার করে এটি ব্যবহার করতে পারেন Marshal.ReadInt16(IntPtr, Int32):

void HandleSecureString(SecureString value) {
  IntPtr valuePtr = IntPtr.Zero;
  try {
    valuePtr = Marshal.SecureStringToGlobalAllocUnicode(value);
    for (int i=0; i < value.Length; i++) {
      short unicodeChar = Marshal.ReadInt16(valuePtr, i*2);
      // handle unicodeChar
    }
  } finally {
    Marshal.ZeroFreeGlobalAllocUnicode(valuePtr);
  }
}

1
এমনকি বহু বছর পরে আমার আপ-ভোট পেয়েছি, সহায়তার জন্য ধন্যবাদ! কেবলমাত্র একটি দ্রষ্টব্য নোট: এটি নিজের স্মৃতিতে স্থির হিসাবেও কাজ করে।
জন স্যুট

আমি চালাতে 4.6sec ব্যবহার করেছি StopWatchএবং SecureStringToStringনিয়েছি took এটা আমার জন্য ধীর। কেউ একই সময় বা দ্রুত কিছু পেতে পারে?
রেডবিএক্স

@ অ্যাডবিএক্স একটি দ্রুত এবং নোংরা পরীক্ষার সেটআপে আমি 76 বারে এটি 1000 বার কল করতে পারি। প্রথম অনুরোধটি 0.3 মিমি এবং পরবর্তী নিমন্ত্রণগুলি ~ 0.07ms নেয়। আপনার সুরক্ষিত স্ট্রিংটি কত বড় এবং ফ্রেমওয়ার্কটির কোন সংস্করণ আপনি ব্যবহার করছেন?
রাসমাস ফাবের

আমার সুরক্ষার দৈর্ঘ্য হল 168 I আমি। নেট ফ্রেমওয়ার্ক 3.5 ব্যবহার করছি যদি সে আপনার প্রশ্নের উত্তর দেয়? আমি চেষ্টা করেছি 5-10 বার সর্বদা প্রায় 4.5-4.65 সেকেন্ডের কাছাকাছি ~ আমি আপনার সময় পেতে পছন্দ করব
রেডবিএক্স

@ রসমাস ফ্যাবার আমার খারাপ, Database.GetConnectionString()আমার সুরক্ষিত স্ট্রিংটি পেতে, আমি আপনার কোডটিতে একটি যুক্ত করেছি, এটি ছিল প্রায় 5 সেকেন্ডের খারাপ অংশ যা ছিল (এবং হ্যাঁ আমি এটি দেখতে হবে! :) আপনার কোডটি আমার স্টপওয়াচে .00 মিলি সেকেন্ড সময় নিয়েছে তাই এটি সব ভালো. আমাকে সঠিক দিকে নির্দেশ করার জন্য ধন্যবাদ।
রেডবিএক্স

108

স্পষ্টতই আপনি জানেন যে এটি কীভাবে একটি সিকিউরস্ট্রিংয়ের পুরো উদ্দেশ্যকে পরাস্ত করে, তবে আমি তা যাইহোক এটি পুনরায় ফিরিয়ে দেব।

যদি আপনি ওয়ান-লাইনার চান তবে এটি ব্যবহার করে দেখুন: (। নেট 4 এবং উপরের কেবল)

string password = new System.Net.NetworkCredential(string.Empty, securePassword).Password;

যেখানে নিরাপদপ্যাসওয়ার্ড একটি সিকিওরস্ট্রিং।


10
যদিও এটি উত্পাদনের উদ্দেশ্যটিকে পরাস্ত করে, আপনার সমাধান ইউনিট পরীক্ষার জন্য উপযুক্ত। ধন্যবাদ।
beterthanLive

এটি আমাকে বুঝতে সাহায্য করেছিল যে আমার সিকিওরস্ট্রিং (সিস্টেম.সিকিউরিটি.সিকিউরস্ট্রিং) আমার অ্যাপি কন্ট্রোলারকে (ওয়েবপি) পাস করা হচ্ছে না। ধন্যবা
granadaCoder

5
পাওয়ারশেলের [System.Net.NetworkCredential]::new('', $securePassword).Password
নোটটি

1
@ TheIncorr وړ1 আপনি কি বিস্তারিত বলতে পারবেন? যেমন কখন ''একই ধরণের হয় না [String]::Empty? এছাড়াও New-Object Net.Credentialআমার জন্য কাজ করে না: টাইপ খুঁজে পাওয়া যাচ্ছে না [Net.Credential]: যাচাই করুন যে সমাবেশ ধারণকারী এই ধরনের লোড হয়
stijn

2
এটি একটি সিকিউরস্ট্রিংয়ের উদ্দেশ্যকে পরাস্ত করে কারণ এটি আপনার সিকিউরস্ট্রিং সামগ্রীটির একটি নন-এনক্রিপ্ট হওয়া অনুলিপিটিকে একটি সাধারণ স্ট্রিংয়ে দেয়। যতবার আপনি এটি করেন, আপনি কমপক্ষে একটি (এবং আবর্জনা সংগ্রহ সম্ভবত একাধিক) সাথে আপনার আনক্রিপ্ট করা স্ট্রিংয়ের কপিগুলিকে মেমরিতে যোগ করছেন to এটি কিছু সুরক্ষা সংবেদনশীল অ্যাপ্লিকেশনগুলির জন্য একটি ঝুঁকি হিসাবে বিবেচিত হয় এবং ঝুঁকি হ্রাস করার জন্য সিকিউরস্ট্রিং বিশেষভাবে প্রয়োগ করা হয়েছিল।
স্টিভ ইন সিও

49

Dang। ঠিক এই পোস্ট করার পরে আমি উত্তরটি এই নিবন্ধটিতে গভীরভাবে পেয়েছি । তবে যদি কেউ এই পদ্ধতিটি উদ্ঘাটন করে এমন इंट্রিটিআরটি নিয়ন্ত্রণহীন, এনক্রিপ্ট না করা বাফারটি কীভাবে অ্যাক্সেস করবেন তা জানেন তবে, আমার সুরক্ষা উঁচু রাখার জন্য আমাকে এটির বাইরে থেকে একটি পরিচালনা স্ট্রিং অবজেক্ট তৈরি করতে না হয়, দয়া করে একটি উত্তর যুক্ত করুন। :)

static String SecureStringToString(SecureString value)
{
    IntPtr bstr = Marshal.SecureStringToBSTR(value);

    try
    {
        return Marshal.PtrToStringBSTR(bstr);
    }
    finally
    {
        Marshal.FreeBSTR(bstr);
    }
}

আপনি অবশ্যই unsafeকীওয়ার্ড এবং একটি ব্যবহার করতে পারেন char*, কেবল কল bstr.ToPointer()এবং কাস্ট করুন।
বেন ভয়েগট

সুরক্ষার জন্য স্ট্রিং ডেটার পরে @ বেনওয়েগ্ট বিএসটিআরটিতে নাল টার্মিনেটর রয়েছে তবে স্ট্রিংয়ের সাথে থাকা শূন্য অক্ষরগুলিকেও অনুমতি দেয়। সুতরাং এটি এর চেয়ে খানিকটা জটিল, আপনাকে সেই পয়েন্টারের আগে যে দৈর্ঘ্যের উপসর্গটি বসেছে তাও পুনরুদ্ধার করতে হবে। ডকস.মাইক্রোসফট.ইন- ইউস
উইম

@ উইমকোয়েন: সত্য তবে গুরুত্বহীন। বিএসটিআরে সঞ্চিত দৈর্ঘ্যটি ইতিমধ্যে উপলব্ধ দৈর্ঘ্যের অনুলিপি হবে SecureString.Length
বেন ভয়েগট

@ বেনভয়েট আহ, আমার খারাপ। আমি ভেবেছিলাম সিকিউরস্ট্রিং স্ট্রিং সম্পর্কে কোনও তথ্য প্রকাশ করেনি।
উইম কয়েনেন

@ উইমকোয়েন: SecureStringমানটি আড়াল করার চেষ্টা করছে না, এটি মূল্য নকলগুলি এমন অঞ্চলে তৈরি করা থেকে রোধ করার চেষ্টা করছে যা নির্ভরযোগ্যভাবে ওভাররাইট করা যায় না, যেমন আবর্জনা সংগ্রহ করা মেমরি, পেজফাইল ইত্যাদি The উদ্দেশ্য হ'ল SecureStringআজীবন শেষ হলে একেবারে গোপনের কোনও অনুলিপি স্মৃতিতে নেই। এটি আপনাকে অনুলিপি তৈরি এবং ফাঁস হতে বাধা দেয় না, তবে তা কখনই করে না।
বেন ভয়েগট

15

আমার মতে, এক্সটেনশন পদ্ধতি হ'ল এটি সমাধানের সবচেয়ে আরামদায়ক উপায়।

আমি স্টিভকে সিও এর দুর্দান্ত উত্তরে নিয়ে গিয়েছিলাম এবং এটিকে একটি এক্সটেনশান ক্লাসে নীচে রেখেছি, দ্বিতীয় পদ্ধতিটির সাথে আমি অন্য দিকটি (স্ট্রিং -> সুরক্ষিত স্ট্রিং) সমর্থন করার জন্য যোগ করেছি, যাতে আপনি একটি সুরক্ষিত স্ট্রিং তৈরি করতে এবং এটিকে রূপান্তর করতে পারেন এর পরে একটি সাধারণ স্ট্রিং:

public static class Extensions
{
    // convert a secure string into a normal plain text string
    public static String ToPlainString(this System.Security.SecureString secureStr)
    {
        String plainStr=new System.Net.NetworkCredential(string.Empty, secureStr).Password;
        return plainStr;
    }

    // convert a plain text string into a secure string
    public static System.Security.SecureString ToSecureString(this String plainStr)
    {
        var secStr = new System.Security.SecureString(); secStr.Clear();
        foreach (char c in plainStr.ToCharArray())
        {
            secStr.AppendChar(c);
        }
        return secStr;
    }
}

এটির সাহায্যে আপনি এখন কেবল নিজের স্ট্রিংকে আগের মতো করে সামনে রূপান্তর করতে পারেন:

// create a secure string
System.Security.SecureString securePassword = "MyCleverPwd123".ToSecureString(); 
// convert it back to plain text
String plainPassword = securePassword.ToPlainString();  // convert back to normal string

তবে মনে রাখবেন ডিকোডিং পদ্ধতিটি কেবল পরীক্ষার জন্য ব্যবহার করা উচিত।


14

আমি মনে করি SecureStringনির্ভরশীল ফাংশনগুলির জন্য মেমরির ডিক্রিপ্টেড স্ট্রিংয়ের (আরও একবার পিন করা) ভাল নিয়ন্ত্রণের জন্য তাদের নির্ভর যুক্তিটিকে একটি অনামী কার্যক্রমে আবদ্ধ করা ভাল।

এই স্নিপেটে সিকিউরস্ট্রিংগুলি ডিক্রিপ্ট করার জন্য প্রয়োগটি হবে:

  1. স্মৃতিতে স্ট্রিংটি পিন করুন (যা আপনি করতে চান তবে বেশিরভাগ উত্তর থেকে এখানে অনুপস্থিত বলে মনে হচ্ছে)।
  2. এর রেফারেন্সটি ফানক / অ্যাকশন প্রতিনিধিটির কাছে পাস করুন ।
  3. এটিকে মেমরি থেকে স্ক্রাব করুন এবং finallyব্লকটিতে জিসিকে ছেড়ে দিন ।

এটি স্পষ্টতই "স্ট্যান্ডার্ডাইজড" করা এবং কলার বনাম বজায় রাখতে খুব সহজ করে তোলে যার চেয়ে কম পছন্দসই বিকল্পগুলির উপর নির্ভর করে:

  • কোনও string DecryptSecureString(...)সহায়ক ফাংশন থেকে ডিক্রিপ্ট করা স্ট্রিংটি ফিরিয়ে দেওয়া ।
  • এই কোডটি যেখানেই প্রয়োজন সেখানে সদৃশ।

এখানে লক্ষ্য করুন, আপনার দুটি বিকল্প রয়েছে:

  1. static T DecryptSecureString<T>যা আপনাকে Funcকলারের কাছ থেকে প্রতিনিধিটির ফলাফল অ্যাক্সেস করতে দেয় ( DecryptSecureStringWithFuncপরীক্ষার পদ্ধতিতে দেখানো হয়েছে )।
  2. 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
}

শুভ কোডিং!


বিভাগের Marshal.Copy(new byte[insecureString.Length], 0, insecureStringPointer, (int)insecureString.Length);পরিবর্তে কেন ব্যবহার করবেন না fixed?
sclarke81

@ sclarke81, ভাল ধারণা, তবে আপনার ব্যবহার করা দরকার [char], তা নয় [byte]
mklement0

1
সামগ্রিক পদ্ধতির প্রতিশ্রুতিবদ্ধ, তবে আমি মনে করি না যে ব্যবস্থাপনিত স্ট্রিংটিতে পিন করার আপনার অনর্থক (প্লেইন-পাঠ্য) অনুলিপি কার্যকরভাবে কার্যকর হবে না: আপনি যা পিন করছেন তার পরিবর্তে মূল স্ট্রিং অবজেক্ট যা আপনি আরম্ভ করেছেন String.Empty, সদ্য বরাদ্দ হওয়া উদাহরণটি তৈরি এবং ফিরে আসে না Marshal.PtrToStringUni()
mklement0

7

আমি rdev5 থেকে উত্তরের ভিত্তিতে নিম্নলিখিত এক্সটেনশন পদ্ধতিগুলি তৈরি করেছি । পরিচালিত স্ট্রিংটি পিন করা গুরুত্বপূর্ণ কারণ এটি আবর্জনা সংগ্রহকারীকে এটিকে চারদিকে ঘোরাতে বা প্রতিরোধ করতে সক্ষম করে যা আপনি মুছে ফেলতে পারছেন না।

আমি মনে করি আমার সমাধানটির সুবিধাটি হ'ল কোনও অনিরাপদ কোডের দরকার নেই।

/// <summary>
/// Allows a decrypted secure string to be used whilst minimising the exposure of the
/// unencrypted string.
/// </summary>
/// <typeparam name="T">Generic type returned by Func delegate.</typeparam>
/// <param name="secureString">The string to decrypt.</param>
/// <param name="action">
/// Func delegate which will receive the decrypted password as a string object
/// </param>
/// <returns>Result of Func delegate</returns>
/// <remarks>
/// This method creates an empty managed string and pins it so that the garbage collector
/// cannot move it around and create copies. An unmanaged copy of the the secure string is
/// then created and copied into the managed string. The action is then called using the
/// managed string. Both the managed and unmanaged strings are then zeroed to erase their
/// contents. The managed string is unpinned so that the garbage collector can resume normal
/// behaviour and the unmanaged string is freed.
/// </remarks>
public static T UseDecryptedSecureString<T>(this SecureString secureString, Func<string, T> action)
{
    int length = secureString.Length;
    IntPtr sourceStringPointer = IntPtr.Zero;

    // Create an empty string of the correct size and pin it so that the GC can't move it around.
    string insecureString = new string('\0', length);
    var insecureStringHandler = GCHandle.Alloc(insecureString, GCHandleType.Pinned);

    IntPtr insecureStringPointer = insecureStringHandler.AddrOfPinnedObject();

    try
    {
        // Create an unmanaged copy of the secure string.
        sourceStringPointer = Marshal.SecureStringToBSTR(secureString);

        // Use the pointers to copy from the unmanaged to managed string.
        for (int i = 0; i < secureString.Length; i++)
        {
            short unicodeChar = Marshal.ReadInt16(sourceStringPointer, i * 2);
            Marshal.WriteInt16(insecureStringPointer, i * 2, unicodeChar);
        }

        return action(insecureString);
    }
    finally
    {
        // Zero the managed string so that the string is erased. Then unpin it to allow the
        // GC to take over.
        Marshal.Copy(new byte[length], 0, insecureStringPointer, length);
        insecureStringHandler.Free();

        // Zero and free the unmanaged string.
        Marshal.ZeroFreeBSTR(sourceStringPointer);
    }
}

/// <summary>
/// Allows a decrypted secure string to be used whilst minimising the exposure of the
/// unencrypted string.
/// </summary>
/// <param name="secureString">The string to decrypt.</param>
/// <param name="action">
/// Func delegate which will receive the decrypted password as a string object
/// </param>
/// <returns>Result of Func delegate</returns>
/// <remarks>
/// This method creates an empty managed string and pins it so that the garbage collector
/// cannot move it around and create copies. An unmanaged copy of the the secure string is
/// then created and copied into the managed string. The action is then called using the
/// managed string. Both the managed and unmanaged strings are then zeroed to erase their
/// contents. The managed string is unpinned so that the garbage collector can resume normal
/// behaviour and the unmanaged string is freed.
/// </remarks>
public static void UseDecryptedSecureString(this SecureString secureString, Action<string> action)
{
    UseDecryptedSecureString(secureString, (s) =>
    {
        action(s);
        return 0;
    });
}

আপনার কোডটি স্ট্রিংয়ের একটি অনুলিপি ফাঁস না করলেও এটি হতাশার গর্তকে উপস্থাপন করেSystem.Stringঅবজেক্টের প্রায় প্রতিটি অপারেশন আনপিনড এবং আনরেসড অনুলিপিগুলি তৈরি করবে। এ কারণেই এটি অন্তর্নির্মিত নয় SecureString
বেন ভয়েগট

নাইস, যদিও শূন্য আউট সমগ্র স্ট্রিং আপনি ব্যবহার করতে হবে new char[length](অথবা সংখ্যাবৃদ্ধি lengthসঙ্গে sizeof(char))।
mklement0

@ বেনভয়েট: যতক্ষণ না actionপ্রতিনিধি অস্থায়ী, পিনযুক্ত, তারপরে শূন্য-আউট স্ট্রিংয়ের অনুলিপি তৈরি না করে, ততক্ষণ এই পদ্ধতির নিজের মতোই নিরাপদ বা অনিরাপদ হওয়া উচিত SecureString- পরবর্তীটি ব্যবহার করার জন্য, একটি সরল-পাঠ্য উপস্থাপনাটিও করতে হবে সুরক্ষিত স্ট্রিংগুলি ওএস-স্তরীয় নির্মাণ নয়; আপেক্ষিক সুরক্ষা আসে সেই স্ট্রিংয়ের আজীবন নিয়ন্ত্রণ করা এবং এটি ব্যবহারের পরে মুছে ফেলা নিশ্চিত করে।
mklement0

@ এমকেলেটমেন্ট ০: SecureStringসদস্য ফাংশন এবং ওভারলোডেড অপারেটর নেই যা সমস্ত জায়গাতেই অনুলিপি করে। System.Stringআছে।
বেন ভয়েগট

1
@ mklement0: কোনটি বিবেচনায় এটি তা পাসের প্রশংসনীয় অভিশাপ কিম্ভুতকিমাকার NetworkCredentialকন্সট্রাকটর যা গ্রহণ করেন SecureString
বেন ভয়েগট

0

এই সি # কোডটি যা আপনি চান তা।

%ProjectPath%/SecureStringsEasy.cs

using System;
using System.Security;
using System.Runtime.InteropServices;
namespace SecureStringsEasy
{
    public static class MyExtensions
    {
        public static SecureString ToSecureString(string input)
        {
            SecureString secureString = new SecureString();
            foreach (var item in input)
            {
                secureString.AppendChar(item);
            }
            return secureString;
        }
        public static string ToNormalString(SecureString input)
        {
            IntPtr strptr = Marshal.SecureStringToBSTR(input);
            string normal = Marshal.PtrToStringBSTR(strptr);
            Marshal.ZeroFreeBSTR(strptr);
            return normal;
        }
    }
}

0

আমি sclarke81 দ্বারা এই উত্তর থেকে প্রাপ্ত । আমি তার উত্তরটি পছন্দ করি এবং আমি ডেরাইভেটিভ ব্যবহার করছি তবে স্কলার্ক 8১ এর একটি বাগ রয়েছে। আমার খ্যাতি নেই তাই মন্তব্য করতে পারি না। সমস্যাটি যথেষ্ট ছোট বলে মনে হচ্ছে এটি অন্য উত্তরের ওয়্যারেন্ট দেয়নি এবং আমি এটি সম্পাদনা করতে পারি। তাই আমি. এটা প্রত্যাখ্যান হয়েছে। সুতরাং এখন আমরা অন্য উত্তর আছে।

sclarke81 আমি আশা করি আপনি এটি দেখতে পেয়েছেন (শেষ পর্যন্ত):

Marshal.Copy(new byte[length], 0, insecureStringPointer, length);

হতে হবে:

Marshal.Copy(new byte[length * 2], 0, insecureStringPointer, length * 2);

এবং বাগ ফিক্স সহ পুরো উত্তর:


    /// 
    /// Allows a decrypted secure string to be used whilst minimising the exposure of the
    /// unencrypted string.
    /// 
    /// Generic type returned by Func delegate.
    /// The string to decrypt.
    /// 
    /// Func delegate which will receive the decrypted password as a string object
    /// 
    /// Result of Func delegate
    /// 
    /// This method creates an empty managed string and pins it so that the garbage collector
    /// cannot move it around and create copies. An unmanaged copy of the the secure string is
    /// then created and copied into the managed string. The action is then called using the
    /// managed string. Both the managed and unmanaged strings are then zeroed to erase their
    /// contents. The managed string is unpinned so that the garbage collector can resume normal
    /// behaviour and the unmanaged string is freed.
    /// 
    public static T UseDecryptedSecureString(this SecureString secureString, Func action)
    {
        int length = secureString.Length;
        IntPtr sourceStringPointer = IntPtr.Zero;

        // Create an empty string of the correct size and pin it so that the GC can't move it around.
        string insecureString = new string('\0', length);
        var insecureStringHandler = GCHandle.Alloc(insecureString, GCHandleType.Pinned);

        IntPtr insecureStringPointer = insecureStringHandler.AddrOfPinnedObject();

        try
        {
            // Create an unmanaged copy of the secure string.
            sourceStringPointer = Marshal.SecureStringToBSTR(secureString);

            // Use the pointers to copy from the unmanaged to managed string.
            for (int i = 0; i < secureString.Length; i++)
            {
                short unicodeChar = Marshal.ReadInt16(sourceStringPointer, i * 2);
                Marshal.WriteInt16(insecureStringPointer, i * 2, unicodeChar);
            }

            return action(insecureString);
        }
        finally
        {
            // Zero the managed string so that the string is erased. Then unpin it to allow the
            // GC to take over.
            Marshal.Copy(new byte[length * 2], 0, insecureStringPointer, length * 2);
            insecureStringHandler.Free();

            // Zero and free the unmanaged string.
            Marshal.ZeroFreeBSTR(sourceStringPointer);
        }
    }

    /// 
    /// Allows a decrypted secure string to be used whilst minimising the exposure of the
    /// unencrypted string.
    /// 
    /// The string to decrypt.
    /// 
    /// Func delegate which will receive the decrypted password as a string object
    /// 
    /// Result of Func delegate
    /// 
    /// This method creates an empty managed string and pins it so that the garbage collector
    /// cannot move it around and create copies. An unmanaged copy of the the secure string is
    /// then created and copied into the managed string. The action is then called using the
    /// managed string. Both the managed and unmanaged strings are then zeroed to erase their
    /// contents. The managed string is unpinned so that the garbage collector can resume normal
    /// behaviour and the unmanaged string is freed.
    /// 
    public static void UseDecryptedSecureString(this SecureString secureString, Action action)
    {
        UseDecryptedSecureString(secureString, (s) =>
        {
            action(s);
            return 0;
        });
    }
}

ভাল যুক্তি; আমি রেফারেন্স করা উত্তরে একটি মন্তব্য রেখেছি, যা ওপিকে অবহিত করা উচিত।
mklement0

0

স্কেলার্ক 8১ সমাধান এবং জন ফ্লাহের্টি ফিক্স অনুসারে চূড়ান্ত কার্যক্ষম সমাধান:

    public static class Utils
    {
        /// <remarks>
        /// This method creates an empty managed string and pins it so that the garbage collector
        /// cannot move it around and create copies. An unmanaged copy of the the secure string is
        /// then created and copied into the managed string. The action is then called using the
        /// managed string. Both the managed and unmanaged strings are then zeroed to erase their
        /// contents. The managed string is unpinned so that the garbage collector can resume normal
        /// behaviour and the unmanaged string is freed.
        /// </remarks>
        public static T UseDecryptedSecureString<T>(this SecureString secureString, Func<string, T> action)
        {
            int length = secureString.Length;
            IntPtr sourceStringPointer = IntPtr.Zero;

            // Create an empty string of the correct size and pin it so that the GC can't move it around.
            string insecureString = new string('\0', length);
            var insecureStringHandler = GCHandle.Alloc(insecureString, GCHandleType.Pinned);

            IntPtr insecureStringPointer = insecureStringHandler.AddrOfPinnedObject();

            try
            {
                // Create an unmanaged copy of the secure string.
                sourceStringPointer = Marshal.SecureStringToBSTR(secureString);

                // Use the pointers to copy from the unmanaged to managed string.
                for (int i = 0; i < secureString.Length; i++)
                {
                    short unicodeChar = Marshal.ReadInt16(sourceStringPointer, i * 2);
                    Marshal.WriteInt16(insecureStringPointer, i * 2, unicodeChar);
                }

                return action(insecureString);
            }
            finally
            {
                // Zero the managed string so that the string is erased. Then unpin it to allow the
                // GC to take over.
                Marshal.Copy(new byte[length * 2], 0, insecureStringPointer, length * 2);
                insecureStringHandler.Free();

                // Zero and free the unmanaged string.
                Marshal.ZeroFreeBSTR(sourceStringPointer);
            }
        }

        /// <summary>
        /// Allows a decrypted secure string to be used whilst minimising the exposure of the
        /// unencrypted string.
        /// </summary>
        /// <param name="secureString">The string to decrypt.</param>
        /// <param name="action">
        /// Func delegate which will receive the decrypted password as a string object
        /// </param>
        /// <returns>Result of Func delegate</returns>
        /// <remarks>
        /// This method creates an empty managed string and pins it so that the garbage collector
        /// cannot move it around and create copies. An unmanaged copy of the the secure string is
        /// then created and copied into the managed string. The action is then called using the
        /// managed string. Both the managed and unmanaged strings are then zeroed to erase their
        /// contents. The managed string is unpinned so that the garbage collector can resume normal
        /// behaviour and the unmanaged string is freed.
        /// </remarks>
        public static void UseDecryptedSecureString(this SecureString secureString, Action<string> action)
        {
            UseDecryptedSecureString(secureString, (s) =>
            {
                action(s);
                return 0;
            });
        }
    }

-5
// using so that Marshal doesn't have to be qualified
using System.Runtime.InteropServices;    
//using for SecureString
using System.Security;
public string DecodeSecureString (SecureString Convert) 
{
    //convert to IntPtr using Marshal
    IntPtr cvttmpst = Marshal.SecureStringToBSTR(Convert);
    //convert to string using Marshal
    string cvtPlainPassword = Marshal.PtrToStringAuto(cvttmpst);
    //return the now plain string
    return cvtPlainPassword;
}

এই উত্তরে একটি স্মৃতি ফুটো আছে।
বেন ভয়েগট

@ বেনওয়েগট আপনি আরও ব্যাখ্যা করতে পারবেন কীভাবে এটির একটি স্মৃতি ফাঁস হয়েছে?
এল রোনোকো

4
@ এলরননোকো: কোনও কিছুই BSTRস্পষ্টতই মুক্তি দেয় না এবং এটি কোনও নেট নেটওয়ার্ক নয় যাতে আবর্জনা সংগ্রহকারীও এটির যত্ন নেন না। স্ট্যাকওভারফ্লো.com/a/818709/103167 এর সাথে তুলনা করুন যা 5 বছর আগে পোস্ট হয়েছিল এবং ফুটো হয় না।
বেন ভয়েগট

এই উত্তরটি উইন্ডোজবিহীন প্ল্যাটফর্মগুলিতে কাজ করে না। পিটিআরটোস্ট্রিংআউটো একটি ব্যাখ্যাটির জন্য ভুল: দেখুন github.com/PowerShell/Powershell/issues/…
কে ফ্র্যাঙ্ক

-5

আপনি যদি একটি এর StringBuilderপরিবর্তে একটি ব্যবহার করেন string, আপনি যখন হয়ে যান তখন আপনি মেমরিতে আসল মানটি ওভাররাইট করতে পারেন। এইভাবে পাসওয়ার্ড মেমরির মধ্যে ঝুলবে না যতক্ষণ না আবর্জনা সংগ্রহ এটি গ্রহণ না করে।

StringBuilder.Append(plainTextPassword);
StringBuilder.Clear();
// overwrite with reasonably random characters
StringBuilder.Append(New Guid().ToString());

2
এটি সত্য হলেও, আবর্জনা সংগ্রহকারী এখনও প্রজন্মের সংযোগের সময় স্ট্রিংবিল্ডার বাফারটিকে মেমরির আশেপাশে সরিয়ে নিতে পারে, যা "প্রকৃত মানটিকে ওভাররাইট" ব্যর্থ করে তোলে, কারণ সেখানে আরও একটি (বা আরও) বাকী অনুলিপি ধ্বংস হয় নি।
বেন ভয়েগট

4
এটি এমনকি দূরবর্তী প্রশ্নের উত্তর দেয় না।
জে সুলিভান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.