Điểm:0

CSPRNG trong Javascript?

lá cờ cn

Tôi đang cố gắng lấy một số khá dài ngẫu nhiên, không thể đoán trước (± 20-25 chữ số) bằng cách sử dụng Javascript (được tạo bởi ứng dụng khách của người dùng) nhanh và nhẹ nhất có thể. Giải pháp này có đáng tin cậy, mạnh mẽ và đủ an toàn không?

Khi trang trực tuyến được mở, dấu thời gian gồm 13 chữ số sẽ được lưu trữ. Bộ đếm thời gian xác định số mili giây trước khi người dùng nhấp vào 'OK' (giả sử anh ta có một đoạn văn bản ngắn để đọc hoặc bất kỳ việc gì khác cần làm). Một bộ sưu tập gồm 100 'pixel' không nhìn thấy được (các khoảng HTML 1*1px) được tạo với các màu RGBA ban đầu được cố định ngẫu nhiên (A=0=độ trong suốt).

 hãy để d = Date.now(); // dấu thời gian 13 chữ số
 đặt n = 100 // số 'pixel' 
 hãy để pixel = ''

 cho (i=0; i<n; i++) {
    hãy để r = Math.floor(Math.random() * 256); 
    hãy để g = Math.floor(Math.random() * 256); 
    hãy để b = Math.floor(Math.random() * 256);
    hãy để c = 'rgba('+r+','+g+','+b+',0)'
    pixel += '<span id="pix'+i+'" style="background-color:'+c+'"></span>'
 }

Sau khi hoàn thành, chúng tôi thay đổi ngẫu nhiên màu của từng 'pixel' cứ sau 100 giây

 hãy để changeColor = setInterval(function(){
    cho (i=0; i<n; i++) {
        hãy để r = Math.floor(Math.random() * 256); 
        hãy để g = Math.floor(Math.random() * 256); 
        hãy để b = Math.floor(Math.random() * 256); 
        hãy để c = 'rgba('+r+','+g+','+b+',0)'
        document.getElementById('pix'+i).style.backgroundColor = c
    }
 },10);

Khi người dùng nhấp vào 'OK', chức năng sẽ dừng lại, một pixel ngẫu nhiên được xác định và các giá trị RGB của nó được tìm thấy

hãy để x = Math.floor(Math.random() * n); // 39
hãy để px = window.getComputedStyle(document.getElementById('pix'+x),null).backgroundColor
để rgb = px.match(/\d+/g); // số điểm 39 = [21,13,152]

Sau đó, chúng tôi nhân mỗi giá trị RGB với x * một hệ số ngẫu nhiên [1 đến 5]:

để r = rgb[0]*(x*Math.floor(Math.random() * 5)+1), // 21 * 39 * 2 = 1638
    g = rgb[1]*(x*Math.floor(Math.random() * 5)+1), // 13 * 39 * 1 = 507
    b = rgb[2]*(x*Math.floor(Math.random() * 5)+1) // 152 * 39 * 4 = 23712

Bằng cách thêm x + bộ đếm thời gian + trích xuất ngẫu nhiên dấu thời gian, chúng tôi thu được:

hãy để t = Date.now()-d; // hẹn giờ khi nhấp chuột
đặt p = Math.floor(Math.random() * 4)+3;    
let z = d.toString().substr(-p) // giá trị dấu thời gian cuối cùng của xx (3->7)

để val = x+''+r+g+b+''+t+z // 39 1368 507 23712 1348 55601

Sau đó, chúng tôi xáo trộn ngẫu nhiên kết quả:

chức năng xáo trộn (a) {
  để r = a.length, temp, rand;
  trong khi (0 !== r) {
    rand = Math.floor(Math.random() * r);
    r -= 1;
    tạm thời = a[r];
    a[r] = a[rand];
    a[rand] = nhiệt độ;
  }
  trả lại một; // 39136850723712134855601 -> 25851963017738613021534
}

  Kiểm tra -> bảng điều khiển
  17:22:34 pixel #39 = [21,13,152] 9348234523267751239843
  17:22:42 pixel #39 = [21,13,152] 109715237240854257137
  17:23:02 pixel #39 = [21,13,152] 100889146450039658553439

Nếu chúng tôi cần kết quả dài hơn (50, 100 chữ số), chúng tôi có thể tạo 500 'pixel' và chọn ngẫu nhiên 10 trong số chúng thay vì một. Hoặc thêm một giá trị entropy (chuyển động của chuột trên màn hình: https://www.grc.com/r&d/js.htm) đến giá trị thu được. Bạn nghĩ sao?

Eugene Styer avatar
lá cờ dz
Từ: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random: Lưu ý: Math.random() không cung cấp các số ngẫu nhiên được bảo mật bằng mật mã. Không sử dụng chúng cho bất cứ điều gì liên quan đến bảo mật. Thay vào đó, hãy sử dụng API Web Crypto và chính xác hơn là phương thức window.crypto.getRandomValues().
Maarten Bodewes avatar
lá cờ in
Vấn đề với sơ đồ này là `Math.random()` không cung cấp các số ngẫu nhiên; thông thường nó được tạo bằng hạt giống 32 bit có thể dễ dự đoán. Vì vậy, đầu vào duy nhất có vẻ hoàn toàn ngẫu nhiên là thời gian giữa các phép tính bắt đầu và người dùng nhấn [OK]. Ồ, và bạn bao gồm cả `Date()`, điều này hoàn toàn không phải là ngẫu nhiên. Điều này ngẫu nhiên như thế nào phụ thuộc vào hệ thống nhiều hơn bất kỳ thứ gì khác mà tôi cho là vậy. Tôi ít nhất mong đợi rằng ai đó có thể lập trình một tập lệnh để bắt đầu phép tính vào một thời điểm nhất định và gần như ngay lập tức có thể buộc nó trở nên rất không ngẫu nhiên.
Maarten Bodewes avatar
lá cờ in
[Điều này sẽ ngẫu nhiên hơn nhiều](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues)
lá cờ ph
Việc sử dụng các pixel màu không cung cấp bất kỳ chức năng nào ngoài việc lưu trữ các giá trị đó trong một mảng.
Điểm:1
lá cờ fr

Math.random không phải là một PRNG bảo mật bằng mật mã. Ví dụ: Firefox sử dụng trình tạo dựa trên XorShift, trình tạo này sẽ rò rỉ toàn bộ trạng thái của nó chỉ sau một vài lệnh gọi. Do đó, bạn không thực sự tạo các pixel ngẫu nhiên ở đây; bạn chỉ đang chọn các giá trị dựa trên cùng một hạt giống trước đó.

MDN mô tả chức năng Web Cryptography API để tạo các số ngẫu nhiên được bảo mật bằng mật mã. Thay vào đó, nếu bạn đang làm việc trong Node.js, thì nó đi kèm với chức năng tích hợp làm điều tương tự. Chúng được thiết kế để triển khai CSPRNG, thường là CSPRNG của hệ thống, mà bạn nên sử dụng trừ khi bạn chắc chắn rằng mình cần thứ gì đó khác. Chúng sẽ phù hợp với hầu hết mọi nhu cầu về mật mã và việc sử dụng hệ thống CSPRNG được hầu hết các nhà mật mã khuyến nghị.

Nếu bạn cần thứ gì đó có thể sao chép được, bạn có thể sử dụng thứ gì đó như ChaCha20 với khóa và nonce được tạo từ hệ thống CSPRNG hoặc HMAC-DRBG với SHA-2 hoặc SHA-3. Tuy nhiên, điều này là không cần thiết trong hầu hết các trường hợp và tốt hơn hết là bạn nên tránh triển khai mật mã của riêng mình để ủng hộ các triển khai đã biết, đáng tin cậy, vì vậy nếu bạn cần điều này, tốt hơn hết bạn nên sử dụng một triển khai đã biết.

Wolden avatar
lá cờ cn
Cảm ơn câu trả lời và ý kiến. Tôi đồng ý với điểm yếu của Math.random nhưng ngoài các vị trí nguyên tắc, liệu nó có làm cho những kết quả thu được này có thể dự đoán được và do đó không an toàn. Nếu vậy, tại sao và như thế nào? Cảm ơn bạn đã giúp hiểu, tôi chẳng là gì ngoài người mới bắt đầu học mật mã ;-)
Wolden avatar
lá cờ cn
như được hiển thị trong 3 dòng cuối cùng của tôi (kiểm tra-> bảng điều khiển) khi chức năng bị dừng, dấu thời gian và pixel được xác định. Tôi đã nhấp rất nhiều lần vào nút OK cho đến khi tôi tìm thấy 3 kết quả cho cùng một pixel (#39): với cùng các giá trị RGB, tôi nhận được 3 kết quả rất khác nhau. Chúng có thể dự đoán được không (tức là trong 'danh sách các kết quả có thể' có thể dự đoán được)?
bk2204 avatar
lá cờ fr
Họ có thể dự đoán đủ rằng cách tiếp cận này phải chịu vũ lực. Chỉ vì nó "có vẻ ngẫu nhiên" không có nghĩa là nó không thể dự đoán được. Tôi sẽ không thực hiện phân tích mật mã đầy đủ về phương pháp này vì tôi nghĩ rằng sử dụng hệ thống CSPRNG rõ ràng là tốt hơn và là lựa chọn hợp lý, nhưng nếu bạn sử dụng `Math.random` làm nguồn ngẫu nhiên mà bạn cần CSPRNG, tôi sẽ yêu cầu một CVE đối với phần mềm của bạn.
Wolden avatar
lá cờ cn
Cảm ơn vì lời giải thích :-)
Điểm:0
lá cờ cn

Tôi đã sử dụng hơn 6 lần hàm Math.random(), một lần để nhận giá trị 0->255 (r,g,b), một lần để nhận giá trị 0->100 (số pixel) và một số khác để nhận các giá trị nhỏ hơn (tức là 3->5 cho dấu thời gian)

Giá trị 0->255 (r,g,b) hiện được lấy từ

    hãy để rand = new Uint8Array(3); // 3 val 0 -> 255
    window.crypto.getRandomValues(rand);
    đặt r = rand[0]; 
    đặt g = rand[1]; 
    đặt b = rand[2];

và giá trị 0->100 (số pixel) từ

    hãy để pix = new Uint8Array(1);
    window.crypto.getRandomValues(pix);
    để v = Math.floor(pix[0]/2.55); // giá trị 0->100

Khi tôi đã thay thế tất cả các hàm Math.random() bằng các triển khai mới này, bạn có nghĩ rằng nó an toàn hơn và đáng tin cậy hơn/chống lại các cuộc tấn công không?

Đăng câu trả lời

Hầu hết mọi người không hiểu rằng việc đặt nhiều câu hỏi sẽ mở ra cơ hội học hỏi và cải thiện mối quan hệ giữa các cá nhân. Ví dụ, trong các nghiên cứu của Alison, mặc dù mọi người có thể nhớ chính xác có bao nhiêu câu hỏi đã được đặt ra trong các cuộc trò chuyện của họ, nhưng họ không trực giác nhận ra mối liên hệ giữa câu hỏi và sự yêu thích. Qua bốn nghiên cứu, trong đó những người tham gia tự tham gia vào các cuộc trò chuyện hoặc đọc bản ghi lại các cuộc trò chuyện của người khác, mọi người có xu hướng không nhận ra rằng việc đặt câu hỏi sẽ ảnh hưởng—hoặc đã ảnh hưởng—mức độ thân thiện giữa những người đối thoại.