วิธีค้นหาฐานข้อมูล MySQL ด้วยฟิลด์ที่เข้ารหัส


15

สมมติว่าฉันต้องเข้ารหัสเขตข้อมูลตารางของฐานข้อมูลMySQL นอกจากนี้ฉันต้องค้นหาบางช่องที่ฉันเข้ารหัส

เราจะค้นหาช่องเหล่านั้นได้อย่างไร

การถอดรหัสแต่ละระเบียนทีละขั้นตอนไม่มีตัวเลือก:สมมติว่าฉันมีหลายพันรายการ จะใช้เวลาและเนื้อที่มากเกินไปในการถอดรหัสแต่ละระเบียนและตรวจสอบว่าแต่ละระเบียนเดี่ยวตรงกับการค้นหาหรือไม่

อัพเดท 2012-09-07

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

อัพเดท 2012-09-08

การเข้ารหัสเป็นเคอร์เนลของคำถามนี้

ข้อ จำกัด การเข้าถึงตามที่เสนอโดยคำตอบบางข้อได้นำไปใช้แล้ว แต่ไม่ตรงกับข้อกำหนดที่เป็นทางการในการเข้ารหัสข้อมูล

ข้อกำหนดอย่างเป็นทางการนี้ไม่ใช่ มาตรฐานความปลอดภัยของข้อมูลอุตสาหกรรมบัตรชำระเงิน [PCI]

คำตอบ:


11

เห็นได้ชัดว่าพวกเขาไม่ได้ตั้งใจจะดูดังนั้นการค้นหาพวกเขาจะเป็นปัญหา

เคล็ดลับหนึ่งที่ฉันใช้ในอดีตคือการแฮชข้อมูลที่เข้ารหัสก่อนที่จะเข้ารหัสและเก็บแฮชในคอลัมน์ที่จัดทำดัชนี แน่นอนมันใช้งานได้เฉพาะเมื่อคุณค้นหามูลค่าทั้งหมด ค่าบางส่วนจะไม่มีแฮชเดียวกัน

คุณอาจขยายเวลานี้ได้โดยสร้างดัชนีแฮชแบบข้อความแบบเต็มหากคุณต้องการ แต่มันอาจซับซ้อนอย่างรวดเร็ว

ภาคผนวก

มีคนแนะนำว่าฉันเพิ่มเชิงอรรถลงในคำตอบของฉันต่อการถกเถียงที่ค่อนข้างยาวในการแชทเกี่ยวกับช่องโหว่ของการโจมตีพจนานุกรมดังนั้นฉันจะพูดถึงความเสี่ยงด้านความปลอดภัยที่อาจเกิดขึ้นกับแนวทางข้างต้น

การโจมตีพจนานุกรม: การโจมตีพจนานุกรมคือเมื่อมีคนแฮชรายการค่าที่ทราบล่วงหน้าล่วงหน้าและเปรียบเทียบการแฮชกับคอลัมน์ที่แฮชของคุณในฐานข้อมูล หากพวกเขาสามารถหาคู่ที่ตรงกันได้อาจเป็นไปได้ว่าค่าที่ทราบนั้นแท้จริงแล้วคือสิ่งที่ถูกแฮช สิ่งนี้มักจะถูกลดทอนลงโดยการเพิ่มค่าด้วยการสุ่ม "เกลือ" ต่อท้ายหรือเสริมเพื่อให้แฮชไม่ตรงกับพจนานุกรม แต่คำตอบข้างต้นไม่สามารถใช้เกลือได้เพราะคุณสูญเสียความสามารถในการค้นหา

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

มันมีอันตรายน้อยกว่าสำหรับรายการที่มีระดับความเป็น cardinality สูงเช่น SSN หมายเลขบัตรเครดิต GUID ฯลฯ (แต่มีความเสี่ยงที่แตกต่างกัน [อ่าน: ถูกกฎหมาย] ที่เกี่ยวข้องกับการจัดเก็บเหล่านี้ดังนั้นฉันจึงไม่แนะนำให้เก็บไว้ )

เหตุผลของเรื่องนี้คือเพื่อให้การโจมตีของพจนานุกรมทำงานได้คุณจะต้องสร้างพจนานุกรมที่มีค่าที่เป็นไปได้และแฮชของพวกเขาไว้ล่วงหน้า ในทางทฤษฎีแล้วคุณสามารถสร้างพจนานุกรมของ SSN ที่เป็นไปได้ทั้งหมด (หนึ่งพันล้านแถวโดยสมมติว่าพีชคณิตการจัดรูปแบบทั้งหมดถูกลบออกไปหลายสิบล้านรายการสำหรับบัตรเครดิต) ... แต่นั่นไม่ใช่จุดของการโจมตีด้วยพจนานุกรมและ โดยทั่วไปจะเทียบเคียงได้กับการโจมตีแบบดุร้ายที่คุณกำลังตรวจสอบทุกค่าอย่างเป็นระบบ

นอกจากนี้คุณยังสามารถมองหาเฉพาะ SSN หรือหมายเลขบัตรเครดิตถ้าคุณกำลังพยายามที่จะตรงกับ SSN ให้คน อีกครั้งมักจะไม่ใช่จุดของการโจมตีด้วยพจนานุกรม แต่เป็นไปได้ที่จะทำดังนั้นหากเป็นความเสี่ยงที่คุณต้องหลีกเลี่ยงคำตอบของฉันไม่ใช่ทางออกที่ดีสำหรับคุณ

ดังนั้นคุณมีมัน เช่นเดียวกับข้อมูลที่เข้ารหัสทั้งหมดโดยปกติแล้วจะมีการเข้ารหัสด้วยเหตุผลดังนั้นควรตระหนักถึงข้อมูลของคุณและสิ่งที่คุณพยายามปกป้อง


การหารือเกี่ยวกับคำตอบนี้ได้รับการย้ายไปแชท
Paul White 9

5

คุณอาจต้องการที่จะดูที่CryptDB มันเป็นส่วนหน้าสำหรับ MySQL และ PostgreSQL ที่ช่วยให้การจัดเก็บโปร่งใสและการสืบค้นข้อมูลที่เข้ารหัส มันทำงานได้โดยการเข้ารหัสและถอดรหัสข้อมูลในขณะที่ผ่านระหว่างแอปพลิเคชันและฐานข้อมูลการเขียนคำสั่งใหม่เพื่อทำงานกับข้อมูลที่เข้ารหัส และโดยการปรับโหมดการเข้ารหัสของแต่ละคอลัมน์แบบไดนามิกเพื่อให้เปิดเผยข้อมูลได้มากเท่าที่จำเป็นสำหรับคิวรีที่แอปพลิเคชันใช้

วิธีการเข้ารหัสต่างๆที่ CryptDB ใช้ ได้แก่ :

  • RNDเป็นรูปแบบการเข้ารหัสที่ปลอดภัย IND-CPA อย่างสมบูรณ์ซึ่งไม่รั่วไหลข้อมูลเกี่ยวกับข้อมูล (ยกเว้นการแสดงตนและสำหรับประเภทความยาวผันแปรความยาว) แต่อนุญาตเฉพาะที่เก็บข้อมูลและการสืบค้นเท่านั้น

  • DETซึ่งเป็นตัวแปรของ RND ซึ่งกำหนดค่าได้ดังนั้นค่าที่เหมือนกันสองค่า (ในคอลัมน์เดียวกัน) จะเข้ารหัสไปยัง ciphertext เดียวกัน WHERE column = 'constant'รองรับคำสั่งความเท่าเทียมกันของรูปแบบ

  • OPEซึ่งเป็นรูปแบบการเข้ารหัสเพื่อรักษาความไม่เท่าเทียมกันที่สนับสนุน queries WHERE column > 'constant'เช่น

  • HOMเป็นรูปแบบการเข้ารหัส homomorphic บางส่วน (Paillier) ซึ่งอนุญาตให้เพิ่มค่าที่เข้ารหัสเข้าด้วยกันโดยการคูณ ciphertexts รองรับการSUM()ค้นหาการเพิ่มและการเพิ่ม

  • การค้นหาWHERE column LIKE '% word %'เป็นโครงการที่สนับสนุนการค้นหาคำหลักของแบบฟอร์ม

  • เข้าร่วมและOPE-JOIN , ตัวแปรของ DET และ OPE ที่อนุญาตให้เปรียบเทียบค่าในคอลัมน์ที่แตกต่างกัน สนับสนุนความเท่าเทียมกันและช่วงเข้าร่วมตามลำดับ

พลังที่แท้จริงของ CryptDB คือปรับวิธีการเข้ารหัสของแต่ละคอลัมน์แบบไดนามิกให้กับคิวรีที่เห็นดังนั้นแบบแผนที่ช้าลงและ / หรือมีความปลอดภัยน้อยจะใช้สำหรับคอลัมน์ที่ต้องใช้เท่านั้น นอกจากนี้ยังมีคุณสมบัติที่มีประโยชน์อื่น ๆ อีกมากมายเช่นการเข้ารหัสคีย์การเข้ารหัสรหัสผ่านผู้ใช้

หากคุณสนใจคุณควรตรวจสอบเอกสารที่เชื่อมโยงจากเว็บไซต์ CryptDB โดยเฉพาะ"CryptDB: การปกป้องความลับด้วย Encrypted Query Processing"โดย Popa, Redfield, Zeldovich และ Balakrishnan ( SOSP 2011 ) เอกสารเหล่านั้นยังอธิบายถึงการแลกเปลี่ยนความปลอดภัยและประสิทธิภาพที่หลากหลายซึ่งเกี่ยวข้องกับการสนับสนุนประเภทการสืบค้นที่แตกต่างกันอย่างละเอียดยิ่งขึ้น


1
It works by encrypting and decrypting data as it passes between the application and the database: แน่นอนว่าสิ่งนี้อาจทำให้เกิดปัญหาหากข้อมูลที่ค้นหาอยู่ในฐานข้อมูล (เข้ารหัส) อยู่แล้ว แต่เห็นได้ชัดว่าแบบสอบถามตัวเองค้นหาฐานข้อมูลนั้นจะถูกส่งผ่านไปยัง CryptDB แล้ว (เข้ารหัสแล้ว?) ฉันไม่เข้าใจวิธีการนี้มีประสิทธิภาพได้อย่างไร
Martin

3

ฉันไม่เข้าใจว่าทำไมคำตอบปัจจุบันไม่ได้ถามข้อกำหนดอย่างเต็มที่ดังนั้นฉันจะถามและทิ้งไว้เป็นคำตอบ

เหตุผลทางธุรกิจคืออะไร คุณต้องการเข้ารหัสข้อมูลอะไรและเพราะเหตุใด หากคุณกำลังมองหาการปฏิบัติตาม PCI ฉันสามารถเขียนเรียงความ

คำถามเกี่ยวกับความต้องการของคุณ:

  • คุณจะต้องส่งคืนผลลัพธ์ที่มีอยู่ / ไม่มีอยู่หรือข้อมูลจริงหรือไม่?
  • คุณต้องการขีดความสามารถ '% OMG_SEKRIT%' LIKE หรือไม่
  • ใครไม่สามารถดูข้อมูลและทำไม

การรักษาความปลอดภัย RDBMS ปกติจะทำบนพื้นฐานของสิทธิ์ที่บังคับใช้โดยผู้ใช้ / บทบาท โดยปกติข้อมูลจะถูกเข้ารหัสโดย RDBMS บนดิสก์ แต่ไม่ได้อยู่ในข้อมูลเรียงเป็นแนวเนื่องจากมันไม่สมเหตุสมผลสำหรับแอปพลิเคชันที่ออกแบบมาเพื่อเก็บและดึงข้อมูลได้อย่างมีประสิทธิภาพ

จำกัด โดยผู้ใช้ / บทบาท / api เข้ารหัสบนดิสก์ หากคุณกำลังเก็บข้อมูลที่สำคัญมากกว่าฉันชอบที่จะรู้ว่าทำไมคุณถึงใช้ MySQL


ในขั้นต้นฉันต้องการค้นหามีอยู่ / ไม่มีอยู่แล้วค้นหาระเบียนที่เฉพาะเจาะจง การรองรับ LIKE แบบเต็มจะดี แต่ฉันสงสัยว่าอะไรที่ตรงกับคำมากเกินจะเป็นไปได้ ผู้ใช้ที่ได้รับอนุญาตได้รับอนุญาตให้ดูข้อมูล แอปถอดรหัสรายการเหล่านั้นผู้ใช้ที่ถูกต้องตามกฎหมายมีสิทธิ์ดู สกีมาพื้นฐานที่อนุญาตไม่มีตัวเลือก
SteAp

เกณฑ์สำหรับ "ข้อมูลสำคัญกว่านี้" คืออะไร
arcanine

2

ฉันกำลังดูสิ่งนี้และเจอคำถามของคุณ ฉันเรียนรู้วิธีการที่อธิบายไว้ในหัวข้อ 5.4 ของบทความ "เทคนิคการปฏิบัติสำหรับการค้นหาข้อมูลที่เข้ารหัส" http://www.cs.berkeley.edu/~dawnsong/papers/se.pdf

ส่วนสำคัญพื้นฐานคือการสร้างดัชนีที่มีคำหลักที่เข้ารหัสที่มีอยู่ในเอกสารการค้นหาที่เข้ารหัส เคล็ดลับคือการเข้ารหัสที่ตั้งในเอกสาร (หรือฐานข้อมูล) ที่มีคำหลักเหล่านั้นอยู่ด้วย


1

โดยทางโปรแกรมแล้วทางออกที่มีประสิทธิภาพคือ

  1. เรียกระเบียนทั้งหมดสำหรับเฉพาะเขตข้อมูลที่คุณกำลังค้นหาด้วยรหัสระเบียน
  2. ถอดรหัสเหล่านั้นลงในตารางชั่วคราว
  3. ทำการค้นหากับตารางนั้น
  4. ใช้รหัสเพื่อดึงข้อมูลระเบียนทั้งหมด (ทุกสาขา) ที่ตรงกับเกณฑ์การค้นหา
  5. ถอดรหัสเหล่านั้นและส่งกลับไปยังผู้ใช้

ประเด็นคือ 1 และ 4 เป็นชุดข้อมูลที่มีขนาดเล็กกว่าการดึงและถอดรหัสฟิลด์ทั้งหมดของระเบียนทั้งหมดในตอนเริ่มต้นอย่างมีนัยสำคัญ

หวังว่าจะช่วย


ตารางชั่วคราวในแบบธรรมดานั้นค่อนข้างง่าย (เช่นมาก) ง่ายต่อการหยิบและอ่านทำลายเซิร์ฟเวอร์ในช่วงเวลาที่เหมาะสมหรือเพียงแค่คัดลอกtemp/โฟลเดอร์และปังค่าธรรมดาสำหรับทั้งคอลัมน์จะมีวิธีนี้ไม่ปลอดภัย
Martin

1

สิ่งนี้เป็นไปได้ด้วยฟังก์ชันการค้นหาแบบเต็มโดยใช้ฟังก์ชันการเข้ารหัสภายในของ MYSQL

นี่คือตัวอย่าง:

!!! ฉันกำลังใช้ MYSQL ENCODE () ที่นี่เพื่อความเรียบง่าย MYSQL_ENCODE กำลังพิจารณาความไม่แน่นอนใช้หนึ่งในฟังก์ชั่น MYSQL ภายในแทน !!!

UPDATE my_table
SET field=ENCODE('my_data', 'my_password')
WHERE ID=1;

SELECT DECODE(field, 'my_password') as field FROM my_table
WHERE field LIKE 'data';

ตามความคิดเห็นข้างต้นแนะนำอย่าใช้ ENCODE () ใช้ฟังก์ชันการเข้ารหัสอื่นอันใดอันหนึ่งที่ฉันใช้ ENCODE ในตัวอย่างนี้เนื่องจากความเรียบง่าย

หากคุณทำสิ่งนี้ภายในแอปพลิเคชันเช่น php คุณสามารถทำได้ภายใน db gateway หรือคลาสที่เก็บข้อมูลของคุณโดยจัดเก็บรายการ / อาร์เรย์ของคอลัมน์ที่เข้ารหัสของแต่ละตารางภายในคลาสเกตเวย์ที่เกี่ยวข้อง

class UserGateway
{
    protected $encrypted_fields = array(
        'username',
        'email'
    );

    public function get($fields, ...)
    {
        foreach ($fields as $k => $field) {
            if (in_array($field, $fields)) {
                $fields[$k] = $this->decodeSelect($field);
            }
        }

        $sql = 'SELECT '.implode(',', $fields);

        //......
    }

    protected function decodeSelect($field)
    {
        return "DECODE($field, $pass) AS $field";
    }
}

แน่นอนว่านี่เป็นรหัสคร่าวๆและไม่ปลอดภัยที่ไม่ควรใช้ในการผลิตหากไม่มีการปรับปรุงที่สำคัญ แต่ควรตอบสนองวัตถุประสงค์ในการให้ความคิดทั่วไป


-1

สมมติว่าคุณกำลังค้นหาใน SQL และเทียบกับค่าเต็มและไม่ใช่บางส่วน (เช่น LIKE 'value%') ... เมื่อจับข้อมูลการค้นหาให้เข้ารหัสข้อมูลโดยใช้อัลกอริทึมเดียวกันกับที่ใช้เมื่อข้อมูลนั้นถูกเข้ารหัสและค้นหาสิ่งนั้น

ตัวอย่างเช่น:

จะเป็นอย่างไร:

SELECT FieldA, FieldB 
FROM Table1 
WHERE FieldC = 'Value'

อาจดูเหมือนว่า:

SELECT FieldA, FieldB 
FROM Table1 
WHERE FieldC = 'hsk&%67ghhks83'

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