Ubah String menjadi SecureString


Jawaban:


137

Kamu tidak. Seluruh alasan menggunakan objek SecureString adalah untuk menghindari pembuatan objek string (yang dimuat ke memori dan disimpan di sana dalam teks biasa hingga pengumpulan sampah). Namun, Anda dapat menambahkan karakter ke SecureString dengan menambahkannya.

var s = new SecureString();
s.AppendChar('d');
s.AppendChar('u');
s.AppendChar('m');
s.AppendChar('b');
s.AppendChar('p');
s.AppendChar('a');
s.AppendChar('s');
s.AppendChar('s');
s.AppendChar('w');
s.AppendChar('d');

13
"Kombinasinya adalah 12345... itu jenis barang yang dimiliki orang idiot di kopernya!"
Kolob Canyon

8
Yang saya lihat hanyalah*****
Ian Boyd

AppendChartidak dieksekusi hingga run time, jadi karakter tersebut masih dapat dibaca dari IL, bukan? Mungkin beberapa kebingungan waktu kompilasi akan membantu juga ... yaitu, jika Anda membuat sandi dengan keras.
samis

5
Itu argumen yang lemah. Di mana Anda mendapatkan kata sandi? Dari formulir atau dari baris perintah. Sampai mereka membuat metode untuk membaca string aman langsung dari perangkat atau argumen baris perintah, kita perlu mengonversi string menjadi SecureString.
Quarkly

1
@DonaldAirey Anda mendapatkan kata sandi dari pengelola rahasia. Umumnya rahasia yang kita bicarakan di sini bukanlah kata sandi pengguna, tetapi hal-hal yang berpotensi menyebabkan eskalasi hak istimewa atau kebocoran data. Itu berarti kata sandi untuk layanan lain, dan tidak boleh diteruskan pada baris perintah atau di bersihkan melalui saluran jaringan.
Barry Kelly

160

Ada juga cara lain untuk mengonversi antara SecureStringdan String.

1. String ke SecureString

SecureString theSecureString = new NetworkCredential("", "myPass").SecurePassword;

2. SecureString ke String

string theString = new NetworkCredential("", theSecureString).Password;

Ini tautannya


4
Sejauh ini, ini adalah solusi terbaik untuk kasus penggunaan yang paling umum!
Dan Bechard

16
Tidak ada gunanya menggunakan a SecureStringjika kode Anda membuat stringobjek dengan nilai yang ingin Anda amankan. Tujuannya SecureStringadalah menghindari string dalam memori yang dikelola, sehingga penyerang yang memeriksa memori tersebut dapat menemukan nilai yang ingin Anda sembunyikan. Karena NetworkCredentialkonstruktor yang Anda panggil memerlukan string, itu bukan cara untuk pergi ... Tentu, kode Anda adalah cara mudah untuk mengkonversi ke dan dari SecureString, tetapi menggunakannya membuat kode Anda seaman menggunakan yang sederhanastring
Gian Paolo

15
@GianPaolo sementara itu benar secara teori, dalam praktiknya kita masih perlu menggunakan SecureStringsaat bekerja dengan beberapa perpustakaan. Dan jujur ​​saja di sini, jika seseorang secara aktif memindai memori aplikasi Anda, maka Anda sudah hilang. Bahkan jika Anda telah menggunakan SecureString dengan benar, yang belum pernah saya lihat, akan ada data berharga lainnya untuk diekstrak.
Jonathan Allen

1
@JonathanAllen: Anda mungkin benar, tetapi hanya karena kami memiliki budaya memperlakukan keamanan sebagai renungan. Jika Anda membuat situs web resep, Korea Utara kemungkinan tidak akan mencoba memindai memori program Anda. Jika Anda menulis perangkat lunak perbankan, ancamannya jauh lebih nyata.
Eric J.

58

metode di bawah ini membantu untuk mengubah string menjadi string aman

private SecureString ConvertToSecureString(string password)
{
    if (password == null)
        throw new ArgumentNullException("password");

    var securePassword = new SecureString();

    foreach (char c in password)
        securePassword.AppendChar(c);

    securePassword.MakeReadOnly();
    return securePassword;
}

26
+1, tetapi perhatikan bahwa meneruskan sandi sebagai parameter string membuat instance string yang tidak terenkripsi dalam memori yang dikelola dan mengalahkan tujuan 'SecureString' sejak awal. Hanya menunjukkan ini untuk orang-orang mendatang yang datang dan menggunakan kode ini.
Cody

19
@Cody Itu benar, dan poin yang bagus, tetapi banyak dari kita tidak peduli apakah SecureString aman atau tidak dan hanya menggunakannya karena beberapa Microsoft API memerlukannya sebagai parameter.
Dan Bechard

3
@Cody Ternyata bahkan kelas SecureString tidak dapat menyimpan string dienkripsi. Itulah sebabnya MS mempertimbangkan untuk menghapus jenis github.com/dotnet/platform-compat/blob/master/docs/DE0001.md .
Martin Brown

19

Anda bisa mengikuti ini:

string password = "test";
SecureString sec_pass = new SecureString();
Array.ForEach(password.ToArray(), sec_pass.AppendChar);
sec_pass.MakeReadOnly();

11

Berikut ini trik linq murah.

            SecureString sec = new SecureString();
            string pwd = "abc123"; /* Not Secure! */
            pwd.ToCharArray().ToList().ForEach(sec.AppendChar);
            /* and now : seal the deal */
            sec.MakeReadOnly();

32
Jawaban ini adalah latihan melihat berapa banyak salinan sementara dari teks biasa yang dapat dihasilkan dalam satu kesempatan
Mike Caron

1
seperti yang disarankan @ john-dagg idenya adalah untuk TIDAK menyetel string dengan sandi Anda karena jika Anda melakukannya, tidak ada keuntungan lagi untuk menggunakan securestring. Dalam kasus Anda, Anda telah memasukkan kata sandi dalam teks biasa, Anda tidak mengamankan apa pun dengan nanti menggunakan securestring. Saya harap Anda memahami bahwa securestring dimaksudkan untuk mengamankan string Anda dari orang-orang yang melihat pembongkaran atau debugger, jadi lihat apa yang ada di IL / memori.
pengguna734028

8

Aku akan membuang ini ke sana. Mengapa?

Anda tidak bisa begitu saja mengubah semua string Anda menjadi string aman dan tiba-tiba aplikasi Anda "aman". String aman dirancang untuk menjaga agar string tetap dienkripsi selama mungkin, dan hanya didekripsi untuk waktu yang sangat singkat, menghapus memori setelah operasi dilakukan padanya.

Saya berani mengatakan bahwa Anda mungkin memiliki beberapa masalah tingkat desain untuk ditangani sebelum khawatir tentang mengamankan string aplikasi Anda. Beri kami beberapa informasi lebih lanjut tentang apa yang Anda coba lakukan dan kami mungkin dapat membantu dengan lebih baik.


1
Saya hanya ingin menggunakannya untuk mengatur kata sandi untuk ProcessStartInfo dan menjalankan exe saya sebagai pengguna yang berbeda .. Itu berhasil untuk saya ...
Developer404

4
Aplikasi saya diamankan dengan menjalankannya di sistem yang aman. Saya tidak peduli tentang string khusus ini yang dienkripsi dalam memori. Ada jauh lebih banyak informasi penting dalam sistem ini yang perlu dikhawatirkan jika pernah dikompromikan. SecureString hanya diperlukan oleh Microsoft API yang perlu digunakan oleh program saya. Tersirat bahwa pengembang mempertimbangkan kasus penggunaannya sendiri dan menentukan apakah mengonversi Strings ke SecureStrings adalah operasi yang valid dalam konteks.
Dan Bechard

Jadi metode ini tidak akan mencegah seseorang untuk melihat kata sandi jika dia menggunakan decompiler seperti DotPeek? Apakah ada cara untuk menyembunyikan string dalam kasus ini?
M.Parent

Ada beberapa metode, tergantung pada ancaman yang Anda coba kalahkan. Jika itu untuk melindungi informasi pengguna dari siapa pun kecuali administrator lokal, Anda dapat menggunakan metode DPAPI di windows untuk mengenkripsi file dan menyimpan rahasia di sana, membacanya menjadi string aman dan kemudian membuangnya. Jika itu untuk rahasia perusahaan, maka jawaban singkatnya adalah jika aplikasi Anda dapat mendekripsinya, begitu juga pengguna pada akhirnya.
Spence

6
unsafe 
{
    fixed(char* psz = password)
        return new SecureString(psz, password.Length);
}

5

tidak ada linq mewah, tidak menambahkan semua karakter dengan tangan, hanya polos dan sederhana:

var str = "foo";
var sc = new SecureString();
foreach(char c in str) sc.appendChar(c);

lebih menarik lagi, tidak perlu mendefinisikan variabel
bigworld12

di sini adalah satu var sc = new SecureString(); foreach(char c in "foo") sc.appendChar(c);
kalimat

4

Saya setuju dengan Spence (+1), tetapi jika Anda melakukannya untuk mempelajari atau menguji pourposes, Anda dapat menggunakan foreach dalam string, menambahkan setiap karakter ke securestring menggunakan metode AppendChar.


3

Saya hanya ingin menunjukkan kepada semua orang yang berkata, "Bukan itu intinya SecureString", bahwa banyak orang yang menanyakan pertanyaan ini mungkin dalam aplikasi di mana, untuk alasan apa pun, dibenarkan atau tidak, mereka tidak terlalu peduli tentang memiliki salinan sementara kata sandi berada di heap sebagai string yang dapat digunakan GC, tetapi mereka harus menggunakan API yang hanya menerimaSecureString objek. Jadi, Anda memiliki aplikasi yang tidak Anda pedulikanapakah kata sandi ada di heap, mungkin itu hanya penggunaan internal dan kata sandi hanya ada di sana karena diperlukan oleh protokol jaringan yang mendasarinya, dan Anda menemukan bahwa string tempat kata sandi disimpan tidak dapat digunakan misalnya untuk mengatur PowerShell jarak jauh Runspace - tetapi tidak ada satu baris yang mudah dan lurus ke depan untuk membuat SecureStringyang Anda butuhkan. Ini adalah ketidaknyamanan kecil - tetapi mungkin sepadan untuk memastikan bahwa aplikasi yang benar - benar membutuhkan SecureStringtidak menggoda penulis untuk menggunakan System.Stringatau System.Char[]perantara. :-)


2

Jika Anda ingin memampatkan konversi dari a stringke a SecureStringmenjadi LINQpernyataan, Anda dapat mengekspresikannya sebagai berikut:

var plain  = "The quick brown fox jumps over the lazy dog";
var secure = plain
             .ToCharArray()
             .Aggregate( new SecureString()
                       , (s, c) => { s.AppendChar(c); return s; }
                       , (s)    => { s.MakeReadOnly(); return s; }
                       );

Namun, perlu diingat bahwa menggunakan LINQtidak meningkatkan keamanan solusi ini. Itu menderita cacat yang sama seperti setiap konversi dari stringmenjadi SecureString. Selama dokumen asli stringtetap ada di memori, data rentan.

Yang sedang berkata, apa yang dapat ditawarkan pernyataan di atas adalah menjaga bersama pembuatan SecureString, inisialisasi dengan data dan akhirnya menguncinya dari modifikasi.


2

2 ekstensi berikut harus melakukan triknya:

  1. Untuk sebuah chararray

    public static SecureString ToSecureString(this char[] _self)
    {
        SecureString knox = new SecureString();
        foreach (char c in _self)
        {
            knox.AppendChar(c);
        }
        return knox;
    }
  2. Dan untuk string

    public static SecureString ToSecureString(this string _self)
    {
        SecureString knox = new SecureString();
        char[] chars = _self.ToCharArray();
        foreach (char c in chars)
        {
            knox.AppendChar(c);
        }
        return knox;
    }

Terima kasih kepada John Dagg atas AppendCharrekomendasinya.


0

Anda dapat menggunakan skrip sederhana ini

private SecureString SecureStringConverter(string pass)
{
    SecureString ret = new SecureString();

    foreach (char chr in pass.ToCharArray())
        ret.AppendChar(chr);

    return ret;
}

1
Jawaban ini diposting 15 bulan yang lalu . Benar-benar tidak perlu mempostingnya lagi.
GSerg
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.