उपयोगकर्ता नाम / पासवर्ड (स्थानीय) को सुरक्षित रूप से कैसे बचाएं?


106

मैं एक विंडोज़ एप्लिकेशन बना रहा हूं, जिसे आपको पहले लॉग इन करना होगा।
खाते के विवरण में उपयोगकर्ता नाम और पासवर्ड शामिल होते हैं, और उन्हें स्थानीय रूप से सहेजने की आवश्यकता होती है।
यह सिर्फ सुरक्षा की बात है, इसलिए समान कंप्यूटर का उपयोग करने वाले अन्य लोग हर किसी के व्यक्तिगत डेटा को नहीं देख सकते हैं।
इस डेटा को बचाने का सबसे अच्छा / सबसे सुरक्षित तरीका क्या है?

मैं डेटाबेस का उपयोग नहीं करना चाहता, इसलिए मैंने संसाधन फ़ाइलों के साथ कुछ चीजों की कोशिश की।
लेकिन जब से मैं इस के साथ नया हूँ, मुझे पूरी तरह से यकीन नहीं है कि मैं क्या कर रहा हूँ और मुझे एक समाधान की तलाश में कहाँ होना चाहिए।


6
सबसे पहले, पासवर्ड सेव न करें। इसे हैश (संभवतः नमक मूल्य के साथ), और इसके बजाय बचाएं।
carlosfigueira

"उपयोगकर्ता" आप नियमित रूप से विंडोज उपयोगकर्ताओं या कुछ और मतलब है? (मुझे लगता है कि आप नियमित रूप से विंडोज उपयोगकर्ता के रूप में आप में से कुछ "उपयोगकर्ताओं" का मतलब है कि पहले से ही एक दूसरे के डेटा को नहीं देख सकते हैं ...)
एलेक्सी लेवेनकोव

मैंने आपका शीर्षक संपादित किया है। कृपया देखें, " क्या सवालों को उनके शीर्षकों में" टैग "शामिल होना चाहिए? ", जहां सर्वसम्मति है "नहीं, उन्हें नहीं करना चाहिए"।
जॉन सॉन्डर्स

@ जॉन सॉन्डर्स ठीक है, मेरी अज्ञानता बहाना।
रॉबिन

2
पूर्ण स्रोत कोड के साथ कोई अंतिम समाधान?
कीकेनेट

जवाबों:


160

यदि आप दर्ज किए गए उपयोगकर्ता नाम और पासवर्ड को सत्यापित / सत्यापित करने जा रहे हैं, तो Rfc2898DerivedBytes वर्ग (पासवर्ड आधारित कुंजी व्युत्पत्ति फ़ंक्शन 2 या PBKDF2 के रूप में भी जाना जाता है) का उपयोग करें। यह ट्रिपल डेस या एईएस जैसे एन्क्रिप्शन का उपयोग करने से अधिक सुरक्षित है क्योंकि पासवर्ड पर वापस RFC2898DerivedBytes के परिणाम से जाने का कोई व्यावहारिक तरीका नहीं है। आप केवल एक पासवर्ड से परिणाम पर जा सकते हैं। देखें यह जब एन्क्रिप्शन कुंजी और चतुर्थ पासवर्ड स्ट्रिंग से पाने के लिए एक नमक के रूप में पासवर्ड की SHA1 हैश का उपयोग करने के लिए ठीक है? WinRT / मेट्रो के लिए पासवर्ड सी # मेट्रो स्टाइल के साथ .Net या स्ट्रिंग एन्क्रिप्ट / डिक्रिप्ट के लिए एक उदाहरण और चर्चा के लिए ।

यदि आप पासवर्ड को पुनः उपयोग के लिए संग्रहीत कर रहे हैं, जैसे कि इसे किसी तीसरे पक्ष को आपूर्ति करना, Windows डेटा सुरक्षा API (DPAPI) का उपयोग करें । यह ऑपरेटिंग सिस्टम जनरेट और प्रोटेक्टेड कीज़ और ट्रिपल डीस एनक्रिप्शन एल्गोरिथम को एन्क्रिप्ट और डिक्रिप्ट करने वाली जानकारी का उपयोग करता है। इसका अर्थ है कि आपके एप्लिकेशन को एन्क्रिप्शन कुंजियों को बनाने और संरक्षित करने के बारे में चिंता करने की आवश्यकता नहीं है, क्रिप्टोग्राफी का उपयोग करते समय एक बड़ी चिंता।

C # में, System.Security.Cryptography.ProtectedData वर्ग का उपयोग करें । उदाहरण के लिए, डेटा का एक टुकड़ा एन्क्रिप्ट करने के लिए, उपयोग करें ProtectedData.Protect():

// Data to protect. Convert a string to a byte[] using Encoding.UTF8.GetBytes().
byte[] plaintext; 

// Generate additional entropy (will be used as the Initialization vector)
byte[] entropy = new byte[20];
using(RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
    rng.GetBytes(entropy);
}

byte[] ciphertext = ProtectedData.Protect(plaintext, entropy,
    DataProtectionScope.CurrentUser);

एंट्रॉपी और सिफरटेक्स्ट को सुरक्षित रूप से स्टोर करें, जैसे कि किसी फ़ाइल या रजिस्ट्री कुंजी में अनुमतियों के साथ सेट करें ताकि केवल वर्तमान उपयोगकर्ता ही इसे पढ़ सके। मूल डेटा तक पहुँचने के लिए, उपयोग करें ProtectedData.Unprotect():

byte[] plaintext= ProtectedData.Unprotect(ciphertext, entropy,
    DataProtectionScope.CurrentUser);

ध्यान दें कि अतिरिक्त सुरक्षा विचार हैं। उदाहरण के लिए, पासवर्ड जैसे गुप्त रहस्यों को संग्रहीत करने से बचें string। स्ट्रिंग्स अपरिवर्तनीय हैं, क्योंकि उन्हें स्मृति में अधिसूचित नहीं किया जा सकता है, इसलिए कोई व्यक्ति एप्लिकेशन की मेमोरी या मेमोरी डंप को देखकर पासवर्ड देख सकता है। उपयोग SecureString या एक बाइट [] के बजाय और निपटान के लिए याद या जैसे ही पासवर्ड अब जरूरत है के रूप में उन्हें शून्य।


नमस्ते, मैंने यह कोशिश की, लेकिन मुझे एन्ट्रापी = rng.GetBytes (20) में एक त्रुटि मिली: यह कहना कि int से बाइट में परिवर्तित नहीं हो सकता []
रॉबिन

@ क्रिसपीएमआरआर मैंने जवाब में कोड का वह टुकड़ा तय किया है। अच्छी पकड़।
अकटन

बहुत बहुत धन्यवाद। मैंने पहली बार हैशिंग के लिए md5 का उपयोग किया था, लेकिन मुझे इस पर संदेह था। यह रास्ता अधिक सुरक्षित लगता है। एक और सवाल हालांकि। मैं इस तरह के कुछ डेटा को एक पाठ फ़ाइल में सहेजना चाहता हूं। मैं देखता हूं कि जब मैं अपनी फ़ाइल खोलता हूं तो यह यादृच्छिक वर्णों का एक समूह होता है, लेकिन क्या ऐसा करना सुरक्षित है? या क्या आप डेटा संग्रहीत करने का दूसरा तरीका सुझाते हैं?
रॉबिन

2
ऐसा लगता है कि वर्ग अब Rfc2898DeriveBytes (छोटे अक्षर, .net 4.5 और 4.6) के रूप में जाना जाता है और यहां पाया जा सकता है: Namespace: System.Security.Cryptography विधानसभा: mscorlib (mscorlib.dll में)
Dashu

2
बहुत जानकारीपूर्ण, हालांकि मुझे लगता है कि उपयोग करने ProtectedDataका पूरा बिंदु ऐसा है कि मुझे स्टोर एन्ट्रापी और सिफरटेक्स्ट के बारे में चिंता करने की ज़रूरत नहीं है , ... इसलिए केवल वर्तमान उपयोगकर्ता ही इसे पढ़ सकता है । मुझे लगता है कि यह सरलता प्रदान करता है कि मैं उन्हें स्टोर कर सकता हूं लेकिन यह सुविधाजनक है और अभी भी केवल करंट यूजर इसे डिक्रिप्ट कर सकता है। entropyपैरामीटर को भी वैकल्पिक है और एक चतुर्थ जहां विशिष्टता गोपनीयता की तुलना में अधिक मायने रखती है के समान प्रतीत होता है। इस प्रकार, मान शायद उन स्थितियों में प्रोग्राम में छोड़ा या कठोर कोडित किया जा सकता है जहां सांद्रता की भिन्नता और अद्यतन अपरिवर्तनीय है।
antak

8

मैंने पहले भी इसका इस्तेमाल किया है और मुझे लगता है कि यह सुनिश्चित करने के लिए कि क्रेडेंशियल कायम रहे और एक बेहतरीन सुरक्षित तरीका है

  1. आप का उपयोग करके उन्हें एप्लिकेशन कॉन्फिग फ़ाइल में लिख सकते हैं ConfigurationManager कक्षा
  2. पासवर्ड का उपयोग करके सुरक्षित करना SecureStringकक्षा
  3. फिर Cryptographyनामस्थान में टूल का उपयोग करके इसे एन्क्रिप्ट करना ।

इस लिंक से मुझे बहुत उम्मीद होगी: यहाँ क्लिक करें


4

DPAPI सिर्फ इस उद्देश्य के लिए है। उपयोगकर्ता द्वारा पहली बार दर्ज किए गए पासवर्ड को एन्क्रिप्ट करने के लिए DPAPI का उपयोग करें, इसे एक सुरक्षित स्थान पर संग्रहीत करें (उपयोगकर्ता की रजिस्ट्री, उपयोगकर्ता के एप्लिकेशन डेटा निर्देशिका, कुछ विकल्प हैं)। जब भी ऐप लॉन्च किया जाता है, तो यह देखने के लिए स्थान देखें कि क्या आपकी कुंजी मौजूद है, अगर वह डीपीएपीआई का उपयोग इसे डिक्रिप्ट करने और एक्सेस की अनुमति देता है, अन्यथा इसे अस्वीकार कर दें।


4

यह केवल विंडोज पर काम करता है, इसलिए यदि आप डॉटनेट कोर क्रॉस-प्लेटफॉर्म का उपयोग करने की योजना बना रहे हैं, तो आपको कहीं और देखना होगा। Https://github.com/dotnet/corefx/blob/master/Documentation/ RGBecture/cross-platform-cryptography.md देखें


यह लिंक मृत है (404)
कार्लोक्स

1

मैं स्ट्रिंग को एक पठनीय स्ट्रिंग के रूप में एन्क्रिप्ट और डिक्रिप्ट करना चाहता था।

यहाँ C # Visual Studio 2019 WinForms में से एक बहुत ही सरल त्वरित उदाहरण है, जिसके उत्तर पर आधारित है @Pradip

राइट क्लिक प्रोजेक्ट> प्रॉपर्टीज> सेटिंग्स> ए usernameऔर passwordसेटिंग बनाएं ।

यहां छवि विवरण दर्ज करें

अब आप उन सेटिंग्स का लाभ उठा सकते हैं जिन्हें आपने अभी बनाया था। यहाँ मैं बचत करता हूँ usernameऔर passwordइसमें केवल passwordसम्मानजनक मूल्य क्षेत्र में एन्क्रिप्ट करता हूँuser.config फ़ाइल ।

user.configफ़ाइल में एन्क्रिप्टेड स्ट्रिंग का उदाहरण ।

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <userSettings>
        <secure_password_store.Properties.Settings>
            <setting name="username" serializeAs="String">
                <value>admin</value>
            </setting>
            <setting name="password" serializeAs="String">
                <value>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAQpgaPYIUq064U3o6xXkQOQAAAAACAAAAAAAQZgAAAAEAACAAAABlQQ8OcONYBr9qUhH7NeKF8bZB6uCJa5uKhk97NdH93AAAAAAOgAAAAAIAACAAAAC7yQicDYV5DiNp0fHXVEDZ7IhOXOrsRUbcY0ziYYTlKSAAAACVDQ+ICHWooDDaUywJeUOV9sRg5c8q6/vizdq8WtPVbkAAAADciZskoSw3g6N9EpX/8FOv+FeExZFxsm03i8vYdDHUVmJvX33K03rqiYF2qzpYCaldQnRxFH9wH2ZEHeSRPeiG</value>
            </setting>
        </secure_password_store.Properties.Settings>
    </userSettings>
</configuration>

यहां छवि विवरण दर्ज करें

पूर्ण कोड

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Security;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace secure_password_store
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Exit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void Login_Click(object sender, EventArgs e)
        {
            if (checkBox1.Checked == true)
            {
                Properties.Settings.Default.username = textBox1.Text;
                Properties.Settings.Default.password = EncryptString(ToSecureString(textBox2.Text));
                Properties.Settings.Default.Save();
            }
            else if (checkBox1.Checked == false)
            {
                Properties.Settings.Default.username = "";
                Properties.Settings.Default.password = "";
                Properties.Settings.Default.Save();
            }
            MessageBox.Show("{\"data\": \"some data\"}","Login Message Alert",MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        private void DecryptString_Click(object sender, EventArgs e)
        {
            SecureString password = DecryptString(Properties.Settings.Default.password);
            string readable = ToInsecureString(password);
            textBox4.AppendText(readable + Environment.NewLine);
        }
        private void Form_Load(object sender, EventArgs e)
        {
            //textBox1.Text = "UserName";
            //textBox2.Text = "Password";
            if (Properties.Settings.Default.username != string.Empty)
            {
                textBox1.Text = Properties.Settings.Default.username;
                checkBox1.Checked = true;
                SecureString password = DecryptString(Properties.Settings.Default.password);
                string readable = ToInsecureString(password);
                textBox2.Text = readable;
            }
            groupBox1.Select();
        }


        static byte[] entropy = Encoding.Unicode.GetBytes("SaLtY bOy 6970 ePiC");

        public static string EncryptString(SecureString input)
        {
            byte[] encryptedData = ProtectedData.Protect(Encoding.Unicode.GetBytes(ToInsecureString(input)),entropy,DataProtectionScope.CurrentUser);
            return Convert.ToBase64String(encryptedData);
        }

        public static SecureString DecryptString(string encryptedData)
        {
            try
            {
                byte[] decryptedData = ProtectedData.Unprotect(Convert.FromBase64String(encryptedData),entropy,DataProtectionScope.CurrentUser);
                return ToSecureString(Encoding.Unicode.GetString(decryptedData));
            }
            catch
            {
                return new SecureString();
            }
        }

        public static SecureString ToSecureString(string input)
        {
            SecureString secure = new SecureString();
            foreach (char c in input)
            {
                secure.AppendChar(c);
            }
            secure.MakeReadOnly();
            return secure;
        }

        public static string ToInsecureString(SecureString input)
        {
            string returnValue = string.Empty;
            IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(input);
            try
            {
                returnValue = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr);
            }
            finally
            {
                System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);
            }
            return returnValue;
        }

        private void EncryptString_Click(object sender, EventArgs e)
        {
            Properties.Settings.Default.password = EncryptString(ToSecureString(textBox2.Text));
            textBox3.AppendText(Properties.Settings.Default.password.ToString() + Environment.NewLine);
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.