ค่าแฮชเกลือควรมาจากที่ใด


12

เมื่อเพิ่มค่าเกลือลงในค่าแฮชสำหรับรหัสผ่านที่ไม่สามารถจัดเก็บในรูปแบบข้อความธรรมดาได้ดีที่สุดวิธีที่จะได้รับค่าเกลือมาจากไหน? สำหรับบริบทให้เราสมมติว่านี่เป็นรหัสผ่านในการเข้าสู่ระบบหน้าเว็บ


@DevArt ฉันคิดว่ามันเหมาะกว่าที่นี่เพราะมันต้องการคำตอบส่วนตัว สามารถดึงค่าเกลือได้จากทุกที่ดังนั้นฉันจึงถาม "คุณคิดว่าตำแหน่งที่ปลอดภัยที่สุดในการดึงค่าเกลือมาจาก: ไคลเอนต์หรือเซิร์ฟเวอร์"
Morgan Herlocker

คำตอบ:


7

ฉันมักจะมีคอลัมน์created TIMESTAMPในตารางผู้ใช้ดังนั้นฉันสามารถดูเมื่อผู้ใช้ลงทะเบียน ฉันไม่ต้องการเพิ่มคอลัมน์เพิ่มเติมสำหรับ Salt ดังนั้นฉันจึงใช้คอลัมน์บันทึกเวลาเป็นเกลือ:

SHA1(password + created)

ฉันสมมติว่าเมื่อผู้ใช้ลงชื่อเข้าใช้อีกครั้งคุณดึงวันที่ตามชื่อผู้ใช้เมื่อคุณทำการยืนยันใหม่
Morgan Herlocker

1
@Prof: ใช่เช่นเดียวกับที่คุณทำถ้าคุณมีคอลัมน์เฉพาะสำหรับเกลือดังนั้นจึงไม่มีความแตกต่างในมุมมองนั้น
Jonas

7

มันสำคัญไหม

เกลือทำหน้าที่สองประการ มันทำให้การใช้รหัสผ่านที่ถูกเตรียมไว้ล่วงหน้าเป็นจำนวนมาก ("โต๊ะรุ้ง") และทำให้รหัสผ่านที่เหมือนกันดูแตกต่างกันในรายการของแฮช การทำให้รหัสผ่านที่เหมือนกันดูแตกต่างกันจะช่วยหลีกเลี่ยงปัญหาที่หลาย ๆ คนกำลังใช้รหัสผ่านเดียวซึ่งน่าจะเป็นรหัสที่อ่อนแอทั่วไป

ดังนั้นแต่ละบัญชีควรมีเกลือเฉพาะของตัวเองและเกลือไม่ควรคาดเดาได้มากเกินไปในแง่ที่ว่าจะไม่มีกลุ่มเกลือที่น่าจะเกิดขึ้น (หากไซต์จำนวนมากเริ่มต้นที่ 1 และนับไว้คนเลวสามารถสร้างตารางสายรุ้งรวมถึงเกลือจำนวนต่ำได้) พวกเขาไม่จำเป็นต้องสุ่มในแง่อื่นนอกเหนือจากที่คาดเดาไม่ได้ พวกเขาไม่ได้เป็นความลับมากกว่าแฮชตัวเองดังนั้นพวกเขาจึงไม่จำเป็นต้องคาดเดาไม่ได้

ใช้วิธีการที่สะดวกในการสร้างเกลือ หากมีค่าเกลือที่เป็นไปได้จำนวนมาก (ระบบ Unix ยุคต้นมักใช้สองไบต์สำหรับจำนวนที่เป็นไปได้ 65536) เมื่อเทียบกับจำนวนบัญชีการกำหนดแบบกึ่งสุ่มจะแทบไม่เคยให้ซ้ำเกลือ


1
ฉันเคยเห็นปัญหาที่สอง - รหัสผ่านที่เหมือนกันนั้นดูแตกต่างกัน - ได้รับการแก้ไขโดยการเชื่อมชื่อผู้ใช้เกลือและรหัสผ่านเข้าด้วยกัน ที่ไม่จำเป็นต้องสร้างเกลือที่ไม่ซ้ำกันต่อบัญชี
Justin Cave

1
@ จัสติน: น่าสนใจฉันไม่เคยเห็นชื่อผู้ใช้ที่ใช้เป็นส่วนหนึ่งของแฮช แต่จริงๆแล้วมันเป็นวิธีที่ดีในการเพิ่มเอนโทรปี ฉันยังคงใช้เกลือแบบหลอกเทียม แต่เพียงเพราะมันไม่ได้มีค่าใช้จ่ายมากนักในการสร้าง
Matthieu M.

2
@Matthieu ด้วยข้อเสียของการต้องเก็บมันไว้ที่ไหนสักแห่งและถ้าทั้งสองด้านของธุรกรรมต้องการมันก็ต้องส่งมันด้วย ด้วยชื่อผู้ใช้ทั้งสองฝ่ายรู้อยู่แล้ว
Matthew Frederick

2
@Justin: ในกรณีนี้คุณใช้ชื่อผู้ใช้เป็นเกลือ มันตอบวัตถุประสงค์ทั้งสองของเกลือ: ทำตารางรุ้งไม่ได้และทำรหัสผ่านที่คล้ายกันดูแตกต่างกัน
David Thornley

@David - จริงคุณสามารถดูได้ว่าชื่อผู้ใช้กลายเป็นส่วนหนึ่งของเกลือ ฉันยังต้องการเกลือเพิ่มเติมเพื่อให้ผู้โจมตีไม่สามารถใช้ตารางรุ้งเพื่อค้นหาชื่อผู้ใช้ / รหัสผ่าน คุณจะเพิ่มขนาดของสตริงที่ผู้โจมตีต้องการจากตารางรุ้งโดยความยาวของชื่อผู้ใช้ (ซึ่งน่าจะสั้นและมีทั้งตัวเล็กและตัวใหญ่) เกลือคงที่นั้นเพียงพอที่จะป้องกันการโจมตีด้วยโต๊ะสีรุ้งหากเว็บไซต์ของคุณมีขนาดใหญ่พอที่ผู้โจมตีจะสร้างตารางรุ้งเฉพาะไซต์
Justin Cave

3

ทุกครั้งที่คุณต้องการจัดเก็บรหัสผ่านใหม่ (การลงทะเบียนการรีเซ็ตรหัสผ่านการอัปเดตรหัสผ่าน) เทคนิคที่ดีอย่างหนึ่งคือ:

  • สร้างเกลือใหม่
    • ใช้ตัวสร้างตัวเลขสุ่มหลอกแบบเข้ารหัสที่ปลอดภัย
    • ใช้เกลือขนาดที่เหมาะสม - ค่าที่ดีคือขนาดบล็อกของอัลกอริทึมแฮชพื้นฐาน (อาจเป็น SHA-256)
  • สร้างโทเค็นรหัสผ่านใหม่
    • สร้างฟังก์ชั่น hmac จากอัลกอริทึมแฮชพื้นฐาน (อาจเป็น SHA-256) โดยใช้เกลือเป็นกุญแจ hmac
    • for i in (0...65536) { password = hmac(password) }
    • ผลลัพธ์ของแอ็พพลิเคชันที่ทำซ้ำของฟังก์ชัน hmac คือโทเค็นรหัสผ่าน
  • เก็บเกลือและโทเค็นรหัสผ่าน
    • อย่าเก็บรหัสผ่านดั้งเดิม
    • เลือกเก็บอัลกอริธึมการแฮชพื้นฐานและส่วนขยายสำหรับการค้นพบ

1

ยกระดับกรอบ ใน. NET คุณสามารถใช้RNGCryptoServoiceProvider ...

        // If salt is not specified, generate it on the fly.
        if (saltBytes == null)
        {
            // Define min and max salt sizes.
            int minSaltSize = 4;
            int maxSaltSize = 8;

            // Generate a random number for the size of the salt.
            Random  random = new Random();
            int saltSize = random.Next(minSaltSize, maxSaltSize);

            // Allocate a byte array, which will hold the salt.
            saltBytes = new byte[saltSize];

            // Initialize a random number generator.
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

            // Fill the salt with cryptographically strong byte values.
            rng.GetNonZeroBytes(saltBytes); 
        }

กรอบงานอื่น ๆ ควรมีคลาสที่คล้ายกันซึ่งคุณสามารถใช้ประโยชน์ได้ เพื่อให้บรรลุถึงซอฟแวร์การสุ่มมักจะมีผู้ใช้งานกับผู้ใช้Randomดังกล่าวข้างต้น TrueCrypt เป็นตัวเลือกการเลื่อนเมาส์ไปรอบ ๆ บริเวณที่กำหนดเพื่อจัดเตรียมเกลือ มันเพิ่มความต้องการและระดับความปลอดภัยของคุณโดยเฉพาะ !@#$%ตั้งแต่เกลือของคุณก็อาจจะ


1

คุณสร้างฝั่งเซิร์ฟเวอร์เกลือและกำหนดให้กับบัญชีผู้ใช้เมื่อมีการสร้าง ใช้ crypto-generation API ที่ดีกว่ากับเฟรมเวิร์กของคุณได้ดีกว่า

โดยปกติสิ่งต่างๆจะถูกเก็บไว้เช่นนี้:

User
-------------------
ID
Username
PasswordHashWithSalt

ตัวอย่าง:

PasswordHashWithSalt =

A15CD9652D4F4A3FB61A2A422AEAFDF0DEA4E703 j5d58k4b56s8744q


กำหนดมันขึ้นอยู่กับว่าอะไร ไม่จำเป็นต้องมาจากค่าบางอย่างที่จะยังคงอยู่เพื่อให้สามารถจำลองได้เมื่อผู้ใช้ลงชื่อเข้าใช้หลังจากการสร้าง?
Morgan Herlocker

ด้วย "มอบหมาย" ฉันหมายถึงสร้างเกลือต่อคู่ชื่อผู้ใช้ / รหัสผ่าน (บัญชี) และเก็บไว้ในฐานข้อมูล เมื่อคุณต้องการทำการเข้าสู่ระบบคุณใช้เกลือที่เก็บไว้เพื่อตรวจสอบสิ่งต่าง ๆ

1

ใช้ bcrypt และอ่านบทความนี้ว่าแฮชปกติเพียงอย่างเดียวไม่ได้รับการปกป้องอย่างจริงจังในยุคนี้

พิจารณาใช้โปรโตคอลรหัสผ่านศูนย์ความรู้ SDRซึ่งมีไลบรารีโอเพนซอร์ซมากมายและไม่มีสิทธิบัตร

SDR ต้องการเกลือและสถานที่ที่ดีที่สุดในการรับคือลูกค้า; เวลาการกดแป้นพิมพ์การเคลื่อนไหวของเมาส์แฮชตัวแปรสภาพแวดล้อมของพวกเขาหมายเลขสุ่มเวลาสร้างไฟล์ในโฟลเดอร์ temp ของพวกเขาเพื่อให้ได้เกลือในตอนท้ายด้วยวิธีที่ไม่อาจคาดเดาได้จากเซิร์ฟเวอร์ของคุณ SDR ใช้เกลือเป็นรหัสเฉพาะขนาดใหญ่รหัสผ่านผู้ใช้และสร้างคีย์ตัวตรวจสอบ คุณไม่ได้จัดเก็บรหัสผ่านที่ไม่เคยออกจากเครื่อง แต่คุณสามารถตรวจสอบได้ว่าพวกเขามีรหัสผ่านที่ไปด้วยคีย์ตัวตรวจสอบและเกลือ มันเป็นภูมิคุ้มกันจากมนุษย์ที่อยู่ตรงกลางและโจมตีพจนานุกรม เข้ารหัสคีย์และเกลือในคอลัมน์ฐานข้อมูลเพื่อให้แน่ใจ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.