Score:0

การเข้ารหัสแบบ One-time-pad ใน C

ธง vn

ฉันได้ยุ่งกับการเข้ารหัส (สำหรับการใช้งานสันทนาการ) และฉันสร้างสคริปต์การเข้ารหัสแบบ one-time-pad ของฉันเองใน C ตอนนี้ฉันยอมรับอย่างอิสระว่าฉันไม่ได้เป็นผู้เชี่ยวชาญด้านการเข้ารหัส ฉันรู้ว่ากฎข้อที่ 1 ของการเข้ารหัสคือห้ามทำด้วยตัวเอง อย่างไรก็ตาม ฉันสนใจจริงๆ ว่าสคริปต์การเข้ารหัสของฉันปลอดภัย (ในทางทฤษฎี) หรือไม่

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

เป้าหมายคือเพื่อให้ได้การเข้ารหัสแบบ One Time Pad ซึ่งใช้ทั้ง (1) ตารางแฮชและ (2) คีย์การเข้ารหัส ตารางแฮช (ในกรณีนี้) ถูกเข้ารหัสไว้ล่วงหน้าโดยมีค่าเป็น 01-98

คีย์การเข้ารหัสคำนวณดังนี้:

  1. รับอินพุตจากผู้ใช้แบบสุ่ม (อย่างน้อยความยาวเท่ากับข้อความ)
  2. รับดัชนีที่สอดคล้องกันสำหรับถ่านใน validChars[] (ซอร์สโค้ดด้านล่าง)
  3. รับตัวเลขใน defaultHashTable ที่สอดคล้องกับดัชนีของ #2

ข้อความถูกเข้ารหัสดังนี้:

  1. รับข้อความและแปลงเป็นค่า defaultHashTable ที่สอดคล้องกัน
  2. นำคีย์ที่สร้างไว้ก่อนหน้านี้และเพิ่มลงในข้อความที่แปลงแล้ว
  3. ตอนนี้มันถูกเข้ารหัสแล้ว (สมมติว่าคีย์เดิมจะไม่ใช้อีก)

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

  1. ข้อความ: สวัสดี
  2. แปลงเป็นค่า defaultHashTable ที่สอดคล้องกัน: สวัสดี -> 0805121215
  3. รับตัวอักษรสุ่มสำหรับคีย์: abkdh
  4. แปลงเป็นค่า defaultHashTable ที่สอดคล้องกัน: abkdh -> 0102110408
  5. เพิ่มรหัส: 0805121215 + 0102110408 = 0907231623
  6. ข้อความเข้ารหัส: 0907231623

นี่คือซอร์สโค้ด (หมายเหตุ: นี่คือการรวมกันของฟังก์ชันที่อยู่ในไฟล์ส่วนหัว C แยกต่างหาก ดังนั้นฉันจึงไม่โพสต์ฟังก์ชัน main ()):

// คีย์ (สำหรับข้อความ) จะมีค่าสูงสุด [50,000][3] (ดังนั้น อาร์เรย์แต่ละตัวจะมีอักขระ 2 ตัว):
โครงสร้าง typedef {
    ปุ่มถ่าน[MAX_SIZE][3];
} สำคัญ;
คีย์ globalKey;

// ข้อความที่เข้ารหัสจะถูกส่งกลับในโครงสร้างนี้ (เพราะเป็นวิธีที่ง่ายในการคืนค่าอาร์เรย์สองมิติจากฟังก์ชันใน C):
โครงสร้าง typedef {
    char encryptedMessage[MAX_SIZE][3];
} ข้อความเข้ารหัส;

// ตารางแฮชเป็นอาร์เรย์สองมิติที่เข้ารหัสไว้ล่วงหน้า (ซึ่งโหลดใน initDefaultHashTable()) ซึ่งจะใช้ร่วมกับคีย์เพื่อเข้ารหัสข้อความ:
// หมายเหตุ: ยังมีโหมดการเข้ารหัสอื่นที่ฉันไม่ได้รวมไว้ (เพื่อพยายามทำให้กระชับ) ซึ่งคุณต้องพิมพ์ตัวเลขสองหลักแบบสุ่มด้วยตนเอง (97 ในนั้น) สำหรับตารางแฮช
โครงสร้าง typedef {
    ถ่าน hashtable [HASHTABLE_CAPACITY][3];
} DefaultHashTable;
DefaultHashTable defaultHashTable; // ประกาศ global defaultHashTable ที่จะเก็บ hashtable นี้

// โหลด defaultHashTable ด้วย 1-98 ตามลำดับ:
เป็นโมฆะ initDefaultHashTable (){
    สำหรับ (int i = 0; i < HASHTABLE_CAPACITY; i++){
        ถ่าน [3];
        sprintf(s, "%d", (i+1));

        ถ้า (ฉัน < 10){
            ถ่าน tmp = s [0];
            s[0] = '0';
            s[1] = tmp;
        }

        สำหรับ (int j = 0; j < 2; j++){
            defaultHashTable.hashtable[i][j] = s[j];
        }
    }
}

// ตัวอักษรที่ถูกต้องที่ข้อความสามารถมีได้ (97 ตัว):
ถ่าน validChars[] = {'a','b','c','d','e','f','g','h','i','j','k', 'l','m','n','o','p','q','r',','t','u','v','w','x ','y','z','A','B','C','D','E','F','G','H','I','J', 'K','L','M','N','O','P','Q','R','S','T','U','V','W ','X','Y','Z','!','@','#','$','%','^','&','*','(', ')','-','+',' ',',','.',':',';','\'','\"','[',']',' {','}','_','=','|','\','/','<','>','?','`','~','\ n','\t','0','1','2','3','4','5','6','7','8','9'};

// สำหรับ char return ล้มเหลว (ฉันรู้สึกว่ามีวิธีที่ดีกว่าในการทำส่วนนี้):
ถ่านล้มเหลว = (ถ่าน)255;

// ค้นหาดัชนีของถ่านที่ถูกต้อง (จาก validChars) หรือ FALSE หากไม่มีอยู่:
int findChar (ถ่าน c) {
    สำหรับ (int i = 0; i < strlen(validChars); i++){
        ถ้า (validChars[i] == ค){
            กลับฉัน;
        }
    }
    กลับ FALSE;
}

// ส่งคืนถ่านจากดัชนี ValidChars ที่กำหนด:
ถ่านกลับถ่าน (ดัชนี int) {
    กลับ validChars [ดัชนี];
}

// รับดัชนีของค่าตารางแฮชที่กำหนด (จาก defaultHashTable) จากนั้น ถ้าทำได้ ถ่านที่เกี่ยวข้องใน validChars:
ถ่าน findHashTableValue (ถ่าน n[3], ถ่าน hashtable[][3]){
    สำหรับ (int i = 0; i < HASHTABLE_CAPACITY; i++){
        ถ้า (hashtable[i][0] == n[0] && hashtable[i][1] == n[1])
            ส่งคืน returnChar (i);
    }
    ส่งคืนล้มเหลว
}

// ส่วนหลักของรหัส (ฟังก์ชัน c หลักจะเรียกสิ่งนี้): เข้ารหัสโดยใช้การเข้ารหัสแผ่นเวลาเดียว แต่ใช้ตารางแฮชเริ่มต้นเพื่อประหยัดเวลา:
เป็นโมฆะ goThroughLightEnryptionProcess (ถ่าน * str, ถ่าน * write_to_file){
     // โหลด defaultHashTable:
    initDefaultHashTable();

    // ใช้ฟังก์ชันเพื่อสร้างคีย์สุ่ม (ขึ้นอยู่กับการป้อนข้อมูลของผู้ใช้แบบสุ่ม):
    createRandomKey(strlen(str), MAX_SIZE, FALSE);

    // เข้ารหัสข้อความ:
    EncryptedMessage encryptMsg = otpEncrypt (defaultHashTable.hashtable, str, globalKey.key);

    // วนซ้ำและพิมพ์เนื้อหา (หากไม่ได้เขียนลงไฟล์):
    ถ้า (write_to_file == NULL){
        สำหรับ (int i = 0; i < strlen(str); i++){
            สำหรับ (int j = 0; j < 2; j++){
                printf("%c", encryptMsg.encryptedMessage[i][j]);
            }
        }
        printf("\n");
    } อื่น {
        // เขียนข้อความที่เข้ารหัสไปยังไฟล์:
        // หมายเหตุ: นี่เป็นพารามิเตอร์อื่นที่คุณสามารถส่งผ่านในโปรแกรมจริง (ซึ่งใหญ่กว่านี้มาก) ซึ่งคุณสามารถเขียนลงในไฟล์แทนการแสดงในเทอร์มินัล:
        // หมายเหตุ: ฉันไม่ได้รวมโค้ดอาร์เรย์ writeFileWithTwoDimensionalArray() นี้ไว้ที่นี่เนื่องจากไม่เกี่ยวข้อง เนื่องจากเป็นเพียงการเขียนไปยังไฟล์
        writeFileWithTwoDimensionalArray (encryptMsg.encryptedMessage, HASHTABLE_CAPACITY, write_to_file);
    }
}

// (ฟังก์ชันตัวช่วย) โหลดอาร์เรย์อักขระสองตัวลงในคีย์:
ถือเป็นโมฆะ loadIntoKeyForRandoKey (int ที่, ถ่าน n [3]){
    สำหรับ (int i = 0; i < 2; i++){
        globalKey.key[ที่][i] = n[i];
    }
}

// สร้างคีย์ตามการป้อนข้อมูลของผู้ใช้แบบสุ่ม:
เป็นโมฆะ createRandomKey (int password_length, int max_size, บูล use_global){
    // @ใช้ globalHashTable | DefaultHashTable
    // @ใช้ globalKey
    ถ่านตอบสนอง [max_size];

    printf("ป้อนอักขระแบบสุ่มสำหรับคีย์ (a-z,A-Z,!@#$%%^&*()-+=, ความยาวขั้นต่ำของ %d): ", password_length);
    fgets (ตอบสนอง, max_size, stdin);

    // ลบอักขระ '\n' ที่ส่วนท้าย:
    ถ่าน * p;
    ถ้า ((p = strchr(การตอบสนอง '\n')) != NULL){
        *p = '\0';
    } อื่น {
        scanf("%*[^\n]");
        scanf("%*ค");
    }

    // ตรวจสอบให้แน่ใจว่าผู้ใช้ป้อนเป็น >= password_length:
    ถ้า (strlen (ตอบกลับ) < password_length){
        printf("\n[ ข้อผิดพลาด ] : อักขระสุ่มต้องมากกว่าหรือเท่ากับ %d.\n", password_length);
        ส่งคืน createRandomKey (password_length, max_size, use_global);
    }

    // แปลงตัวอักษรสุ่มให้มีค่าเท่ากันใน hashtable ตามลำดับ:
    สำหรับ (int i = 0; i < password_length; i++){
        int getCharIndex = findChar (ตอบกลับ [i]);
        
        // ตรวจสอบให้แน่ใจว่าพบเรียบร้อยแล้ว:
        ถ้า (getCharIndex == FALSE){
            printf("\n[ ข้อผิดพลาด ] ตัวอักษร '%c' ไม่ถูกต้อง ลองอีกครั้ง\n", ตอบกลับ[i]);
            ส่งคืน createRandomKey (password_length, max_size, use_global); // ทำมันอีกครั้ง
        }

        // โหลดค่า hashtable ที่สอดคล้องกันลงในคีย์:
        ถ้า (use_global == จริง){
            loadIntoKeyForRandoKey (i, globalHashTable.hashtable[getCharIndex]);
        } อื่น {
            loadIntoKeyForRandoKey (i, defaultHashTable.hashtable[getCharIndex]);
        }
    }

    // เขียนคีย์สุ่มไปยังไฟล์:
    createFileWithTwoDimensionalArray (globalKey.key, password_length, "คีย์");
}

// (ฟังก์ชันตัวช่วย) สำหรับการโหลดลงในโครงสร้าง EncryptedMessage:
ถือเป็นโมฆะ loadIntoEncryptedMessage (int at, char n[3], EncryptedMessage *encryptedMsg){
    ถ้า (strlen(n) == 1){
        // ต่อท้าย '0':
        ถ่าน tmp = n[0];
        n[0] = '0';
        n[1] = tmp;
    }

    สำหรับ (int i = 0; i < 2; i++){
        encryptedMsg->encryptedMessage[ที่][i] = n[i];
    }
}

/*
    เข้ารหัสข้อความที่กำหนดแฮชเทเบิลและคีย์ที่ถูกต้อง
*/
EncryptedMessage otpEncrypt(char hashtable[][3], char * msg, char key[MAX_SIZE][3]){
    EncryptedMessage encryptedMsg;

    สำหรับ (int i = 0; i < strlen(msg); i++){
        // แปลงค่าคีย์เป็นจำนวนเต็ม:
        int ConvertKeyValueIntoInt = safeConvertToInt(คีย์[i]);

        // ตรวจสอบให้แน่ใจว่าแปลงอย่างถูกต้อง:
        ถ้า (แปลง KeyValueIntoInt == FALSE){
            printf("[ ERROR ] : คีย์เสียหายที่ %d (ค่า = %s)\n", i, คีย์[i]);
            ทางออก (1);
        }

        // แปลงข้อความของผู้ใช้ให้เทียบเท่าใน hashtable:
        int indexOfMsgChar = findChar(msg[i]);

        // ตรวจสอบให้แน่ใจว่า findChar() พบค่าอย่างถูกต้อง:
        ถ้า (indexOfMsgChar == FALSE){
            printf("[ ERROR ] : รหัสผ่าน (msg) เสียหายที่ %d (ค่า = %s) สิ่งนี้อาจเกิดขึ้นเนื่องจากไม่อนุญาตให้ใช้อักขระ '%c'\n", i, msg, msg[i ]);
            ทางออก (1);
        }

        ถ่าน * ที่สอดคล้องกันEncryptMsgChars = hashtable [indexOfMsgChar];

        // แปลงตัวอักษร encryptMsg ที่สอดคล้องกันเป็น int:
        int ConvertEncryptMsgCharsIntoInt = safeConvertToInt (ที่สอดคล้องกันEncryptMsgChars);

        // ตรวจสอบให้แน่ใจว่าแปลงอย่างถูกต้อง:
        ถ้า (แปลงEncryptMsgCharsIntoInt == FALSE){
            printf("[ ข้อผิดพลาด ] : ตารางแฮชเสียหายที่ %d (ค่า = %s)\n", indexOfMsgChar, สอดคล้องEncryptMsgChars);
            ทางออก (1);
        } 

        // ทำการคำนวณ:
        int encryptedFrag = otpeAdd (แปลง EncryptMsgCharsIntoInt, ConvertKeyValueIntoInt);
        
        // แปลงเป็นสตริง:
        ถ่านเข้ารหัส FragStr [3];
        sprintf(encryptedFragStr, "%d", encryptedFrag);
        
        loadIntoEncryptedMessage(i, encryptedFragStr, &encryptedMsg);
    }
    ส่งคืน encryptedMsg;
}

คำถามทันทีของฉันคือ: ถ้าฉันใช้ตารางแฮชที่เข้ารหัสไว้ล่วงหน้า (ที่ใครๆ ก็อนุมานได้) นั่นทำให้การเข้ารหัสไม่ปลอดภัย (แม้ว่าคีย์ที่สอดคล้องกับค่าตารางแฮชจะสุ่มโดยสมบูรณ์ผ่านการป้อนข้อมูลของผู้ใช้) จะปลอดภัยก็ต่อเมื่อฉันสุ่มหมายเลขตารางแฮช (01-98) (และอาจสุ่มค่า validChars[])

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

Paul Uszak avatar
cn flag
สวัสดี ตัวเลือกที่ยอดเยี่ยมในการใช้ OTP แต่ _"(1) รับอินพุตของผู้ใช้แบบสุ่ม (อย่างน้อยความยาวเท่ากับข้อความ)"_ ยังไง? หากฉันเข้ารหัสข้อความขนาดทวีต ข้อมูลสุ่มจะมาจากไหน โปรดจำไว้ว่า OTP **มี** จะต้องสร้างทางกายภาพผ่านฮาร์ดแวร์เชิงกลหรือทางชีวภาพ **ไม่ใช่** ซอฟต์แวร์
vn flag
@PaulUszak สวัสดี! ขณะนี้ฉันได้รับอินพุตจากผู้ใช้แบบสุ่มโดยให้ผู้ใช้พิมพ์อักขระแบบสุ่มที่มีความยาวหรือมากกว่าข้อความ ปลอดภัยหรือไม่?
zw flag
มนุษย์น่ากลัวอย่างไม่อาจปฏิเสธได้ในการสร้างข้อมูลแบบสุ่ม OTP *ต้องการตามคำนิยาม* อินพุตแบบสุ่มอย่างแท้จริงเป็นคีย์ของมัน
Score:1
ธง cn

ปัญหาสามประการปรากฏขึ้นทันที:-

  1. เกาลัดเก่าของความสมบูรณ์ของข้อความ แพดแบบใช้ครั้งเดียวล้วนไม่มีวิธีการยืนยันตัวตนใดๆ ทั้งสิ้น กล่าวคือ มีอยู่จริง อ่อน.

  2. คีย์ (สำหรับข้อความ) จะมีจำนวนสูงสุด [50,000]. ฉันได้พูดคุยเกี่ยวกับข้อความขนาดทวีตโดยเฉพาะด้วยเหตุผลเดิมที OTP ถูกสร้างขึ้นผ่านเครื่องพิมพ์ดีดและประสบความสำเร็จอย่างมาก แต่พวกเขามีขนาดเล็กและน่าจะมีคนพิมพ์ดีดมากมาย ไม่มีการทดสอบทางสถิติใดที่สามารถหักล้างการสุ่ม 160 ตัวอักษรได้ (พิมพ์อย่างมีเหตุผล) แต่มีสำหรับ 50,000 ไม่น่าเป็นไปได้อย่างยิ่งที่ 50,000 อักขระที่พิมพ์แบบสุ่มบนแป้นพิมพ์จะเป็นเช่นนั้น การวิเคราะห์ความถี่และฮิวริสติกจะปรับลดระดับความปลอดภัยของข้อมูล OTP ลงอย่างมาก และผู้ใช้จะพิมพ์ 50,000 ตัวอักษรจริงหรือ อุปกรณ์ฮาร์ดแวร์ (TRNG) จำเป็นสำหรับคีย์ขนาดดังกล่าว

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

3½ตารางแฮชค่อนข้างไม่จำเป็น เพียงใช้ค่า ASCII เนื่องจากความปลอดภัยภายใน OTP มาจากคีย์ มันคุ้มค่าที่จะอ่านคำถามที่ติดแท็ก OTP บางข้อ ที่นี่.

Score:0
ธง zw

มันคือ มาก ของรหัสสำหรับบางสิ่งที่ทำให้:

เป็นโมฆะ otp (size_t len, uint8_t *คีย์, uint8_t *ข้อความ) {
    สำหรับ (size_t i = 0; i < len; i++) {
        ข้อความ[i] ^= คีย์[i];
    }
}

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

ถ่าน * คีย์ = มัลลอค (เลนส์);

ยืนยัน (คีย์ != NULL);
ยืนยัน (อ่าน (fd, คีย์, len) == len);

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

แผ่นครั้งเดียว ต้อง มีปุ่มสุ่มอย่างแท้จริง อักขระที่พิมพ์บนแป้นพิมพ์ไม่ใช่การสุ่มอย่างแท้จริง ผลลัพธ์ของ /dev/สุ่ม ไม่สุ่มอย่างแท้จริง การรับบิตแบบสุ่มนั้นยาก แต่มีอุปกรณ์ภายนอกที่จะรวบรวมให้คุณ (สมมติว่าคุณเชื่อถืออุปกรณ์นั้น) กุญแจเหล่านั้น ต้อง มีความยาวเท่ากับข้อความของคุณ (หรือนานกว่านั้น ฉันคิดว่า)

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

Mark avatar
ng flag
เป็นมูลค่าการกล่าวขวัญว่า "แพดแบบใช้ครั้งเดียวต้องมีคีย์สุ่มอย่างแท้จริง" นั้นไม่เป็นความจริงทั้งหมด --- คุณสามารถแทนที่แหล่งสุ่มด้วย PRG (ในโหมดตัวนับ) เพื่อรับ $\mathsf{CTR}\$$ การเข้ารหัส แน่นอนว่าสิ่งนี้ไม่ปลอดภัยอย่างสมบูรณ์ แต่อาจคุ้มค่าที่จะกล่าวถึงสำหรับผู้มาใหม่สำหรับการใช้งานการเข้ารหัสอย่างง่ายโดยเฉพาะ
zw flag
ณ จุดนั้น มันคือการเข้ารหัสของสตรีม ไม่ใช่แพดแบบใช้ครั้งเดียว นี่ไม่ใช่แค่ความแตกต่างทางวิชาการ แต่หมายถึงปมของงานทั้งหมดที่แตกต่างกันโดยพื้นฐานแล้ว ไม่ใช่แค่บิต XORing เท่านั้น ส่วนที่ยากคือการออกแบบและเขียน CSPRNG
Mark avatar
ng flag
ใช่ แต่ก็ยังมีประโยชน์ในเชิงแนวคิดในการทำความเข้าใจรหัสสตรีม OTP นั้นมีแนวคิดที่เรียบง่าย แต่การจัดการคีย์นั้นยาก CTR$ แทนที่การจัดการคีย์ (ยาก) ด้วยปัญหา (ยาก) ของการออกแบบ PRG โชคดีที่แม้ว่าทั้งสองอย่างจะยาก แต่ดูเหมือนว่าเราจะสามารถออกแบบ PRG ได้ ในขณะที่การจัดการคีย์ OTP ตามขนาดจริงดูเหมือนจะสิ้นหวัง (ส่วนใหญ่)
Paul Uszak avatar
cn flag
น่าสนใจ. ทำไมคุณถึงเชื่อว่า `/dev/random` ไม่ใช่การสุ่มอย่างแท้จริง? ฉันหมายถึงคนที่บล็อก (ed) (s) คุณกำลังพูดถึงอันใหม่หรือไม่? นอกจากนี้ มันไม่ _that_ ยากเพราะคุณสามารถทำได้โดยไม่ต้องใช้ชุดอุปกรณ์ภายนอกเลย - cpu jitter - `System.nanoTime()` หรือ `haveged` หรือไลบรารีเอนโทรปีของ Arduino
zw flag
`/dev/random` และ `/dev/urandom` [ทั้งคู่ส่งออกจาก CSPRNG เดียวกันทุกประการ](https://www.2uo.de/myths-about-urandom/) แม้ว่าคุณจะต้องการโต้แย้งว่าเคอร์เนลประมาณอัตราส่วน 1:1 ระหว่างเอนโทรปีอินพุตและเอนโทรปีเอาต์พุตจากในอดีต การรับประกันดังกล่าวจะหมดไปเมื่อคุณส่งผ่าน CSPRNG ซึ่งรับประกันความปลอดภัยในการคำนวณเท่านั้นและไม่มีหลักฐานยืนยัน ของความปลอดภัยที่สมบูรณ์แบบ `haveged` เพิ่มเอนโทรปีให้กับตัวประมาณค่าเอนโทรปีของเคอร์เนล แต่สิ่งนี้ก็ยังพบปัญหาพื้นฐานเดียวกัน
zw flag
ทั้งสองวิธี ประเด็นไม่ใช่ว่ามันเป็นไปไม่ได้ที่จะได้ตัวเลขสุ่มอย่างแท้จริง ประเด็นก็คือ OTP นั้นเป็นเรื่องเล็กน้อยโดยพื้นฐานแล้ว ส่วนที่ "ยาก" คือการได้รับตัวเลขที่สุ่มจริง ๆ และไม่ใช่การสุ่มที่ "ดูดีสำหรับฉัน" และแน่นอน ถ้าคุณมีแชนเนลที่คุณสามารถแบ่งปันอย่างปลอดภัยกับบุคคลที่สาม คุณก็อาจจะแลกเปลี่ยนข้อความผ่านแชนเนลนั้นได้เช่นกัน

โพสต์คำตอบ

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