การเข้ารหัสอาณาจักรด้วยคีย์ที่จัดเก็บไว้ใน KeyStore

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

สิ่งที่ฉันทำ

นี่คือวิธีที่ฉันสร้างคีย์:

  KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
        ks.load(null);

        if (!ks.containsAlias(KEY_ALIAS)) {

            Calendar start = Calendar.getInstance();
            Calendar end = Calendar.getInstance();
            end.add(Calendar.YEAR, 99);

            KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(this)
                    .setAlias(KEY_ALIAS)
                    .setSubject(new X500Principal("CN=Example, O=ExampleOrg"))
                    .setSerialNumber(BigInteger.ONE)
                    .setStartDate(start.getTime())
                    .setEndDate(end.getTime())
                    .build();

            KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
            generator.initialize(spec);

            KeyPair keyPair = generator.generateKeyPair();
        }

ฉันใช้ KeyPairGenerator เนื่องจากฉันต้องรองรับ API เวอร์ชัน 18 ขึ้นไป

นี่คือวิธีที่ฉันตั้งค่าอินสแตนซ์ขอบเขตเริ่มต้นในแอปพลิเคชันของฉัน:

 RealmConfiguration config = null;
    try {
        config = new RealmConfiguration
                .Builder(this)
                .encryptionKey(ks.getKey(KEY_ALIAS, null).getEncoded())
                .name("dealmatrix.realm")
                .schemaVersion(1)
                .build();

โดยที่ ks เป็นอินสแตนซ์ Keystore ที่ได้รับดังนี้:

Keystore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);

เกิดอะไรขึ้น

ปัญหาของฉันคือนิพจน์นี้:

ks.getKey(KEY_ALIAS, null).getEncoded()

คืนค่า null ซึ่งนำไปสู่ข้อยกเว้นอย่างเข้าใจได้

ฉันได้อ่านออนไลน์แล้วว่านี่เป็นพฤติกรรมที่ตั้งใจไว้ของระบบ KeyStore

หากฉันไม่สามารถรับอาร์เรย์ไบต์ของคีย์เข้ารหัสที่เก็บไว้ได้ ฉันจะเข้ารหัสขอบเขตของฉันโดยใช้คีย์ดังกล่าวได้อย่างไร

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


person Rakatan    schedule 08.04.2016    source แหล่งที่มา
comment
คุณทราบวิธีแก้ปัญหาใด ๆ บ้างไหม ฉันก็ประสบปัญหานี้เช่นกัน   -  person Bala Saikrupa Puram    schedule 13.02.2018


คำตอบ (3)


มีโปรเจ็กต์ตัวอย่าง WIP ในสาขา feature/example/store_password ในพื้นที่เก็บข้อมูล Realm ซึ่งใช้ที่เก็บคีย์ Android

https://github.com/realm/realm-java/tree/feature/example/store_password/examples/StoreEncryptionPassword

ตรรกะหลักเขียนไว้ใน Store.java

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

person zaki50    schedule 01.05.2016

คีย์ Android Keystore ที่ส่งคืนค่า null จาก getEncoded ทำงานตามที่ตั้งใจไว้ getEncoded ควรส่งคืนเนื้อหาคีย์ส่วนตัว (โดยปกติจะอยู่ในรูปแบบที่เข้ารหัส PKCS#8 DER) หรือเป็นค่าว่างหากไม่รองรับการส่งออกเนื้อหาคีย์ Android Keystore ตามการออกแบบไม่เปิดเผย/ส่งออกเนื้อหาคีย์ของคีย์ส่วนตัวหรือคีย์ลับ ดังนั้น getEncoded จึงส่งคืนค่าว่าง ดู https://developer.android.com/training/articles/keystore.html#SecurityFeatures

คุณยังคงสามารถใช้คีย์เหล่านี้ได้ดีกับนามธรรมของลายเซ็นและการเข้ารหัส

person Alex Klyubin    schedule 10.04.2016
comment
โอเคฉันเข้าใจ. สิ่งที่คุณพูดก็สมเหตุสมผล แต่นี่ไม่ได้ตอบคำถามของฉันจริงๆ ฉันจะจัดเก็บคีย์เข้ารหัสสำหรับการกำหนดค่า Realm ของฉันอย่างปลอดภัยได้อย่างไร - person Rakatan; 11.04.2016
comment
อาณาจักรคืออะไร? โดยทั่วไป คุณสามารถเข้ารหัสสิ่งต่างๆ ได้โดยใช้ Cipher primitive ซึ่งคุณเริ่มต้นด้วยอินสแตนซ์คีย์ ในกรณีนี้ คุณสามารถรับอินสแตนซ์คีย์ได้จาก Android Keystore - person Alex Klyubin; 11.04.2016
comment
realm.io มันเป็นฐานข้อมูล ฉันทราบวิธีการทำงานของ Keystore แต่วิธีการเข้ารหัสของฐานข้อมูลยอมรับเฉพาะอาร์เรย์ไบต์เท่านั้น - person Rakatan; 11.04.2016
comment
ในกรณีดังกล่าว ดูเหมือนว่า realm.io เข้ากันไม่ได้กับ crypto ที่ไม่รั่วไหลเนื้อหาสำคัญในกระบวนการที่ realm.io กำลังทำงานอยู่ เช่น Android Keystore crypto - person Alex Klyubin; 12.04.2016

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

แต่หากต้องการจัดเก็บคีย์ Realm นั้นอย่างปลอดภัย คุณจะต้องใช้ประสิทธิภาพของที่เก็บคีย์ Android โดยการเข้ารหัสคีย์ Realm ด้วยที่เก็บคีย์ Android จากนั้นจัดเก็บไว้ในเครื่อง (เช่น การตั้งค่าที่ใช้ร่วมกัน) หลังจากนั้นคุณสามารถอ่านคีย์ Realm ที่เข้ารหัสนั้น ถอดรหัสด้วย Android Keystore และใช้อีกครั้งเพื่อปลดล็อกฐานข้อมูล Realm ของคุณ

person Stefan Arn    schedule 01.03.2019