2010-03-31 33 views
24

Xây dựng một thuật toán đơn giản tạo ra một tệp không chứa gì ngoài kiểm tra của chính nó.Làm thế nào để tìm một tổng kiểm tra của cùng một tổng kiểm tra? (câu hỏi phỏng vấn xin việc)

Giả sử đó là CRC-32, vì vậy tệp này phải dài 4 byte.

+2

Có nhiều cách tính tổng kiểm tra, và chắc chắn không phải là thuật toán phổ biến để loại tệp này độc lập với thuật toán tính toán tổng kiểm tra lực lượng thử và sai). Thuật toán CS đã được chỉ định chưa? –

+2

Làm cách nào để tính tổng kiểm tra? SHA1, MD5, hoặc bất cứ điều gì tôi chọn, bởi vì nếu tôi có thể chọn thuật toán tổng kiểm tra, điều này tôi khá tầm thường. –

+2

về cơ bản bạn đang tìm một hàm điểm cố định, trong đó f (x) = x. –

Trả lời

33

Có thể có một số cách toán học thông minh để tìm ra (hoặc chứng minh rằng không tồn tại), nếu bạn biết cách hoạt động của thuật toán.

Nhưng vì tôi lười biếng và CRC32 chỉ có 2^32 giá trị, tôi sẽ bạo lực. Trong khi chờ thuật toán đi qua tất cả 2^32 giá trị, tôi sẽ sử dụng Google và Stack Overflow để tìm xem liệu ai đó có giải pháp cho nó hay không.

Trong trường hợp SHA-1, MD5 và các thuật toán bảo mật mã hóa khác ít hơn, tôi sẽ bị đe dọa bởi các nhà toán học đã thiết kế các thuật toán đó và từ bỏ.

CHỈNH SỬA 1: Đay buộc ... Điều này đến nay tôi đã tìm thấy một; CC4FBB6A trong mã hóa lớn. Có thể vẫn còn nhiều hơn nữa. Tôi đang kiểm tra 4 mã hóa khác nhau: chữ hoa và chữ thường ASCII, và nhị phân lớn và cuối nhỏ.

CHỈNH SỬA 2: Hoàn thành lực lượng vũ phu. Dưới đây là kết quả:

CC4FBB6A (lớn-endian)
FFFFFFFF (lớn-endian & ít về cuối nhỏ)
32F3B737 (chữ hoa ASCII)

Mã này là here. Trên C2Q6600 ép xung của tôi mất khoảng 1,5 giờ để chạy. Bây giờ chương trình đó là đơn luồng, nhưng nó sẽ dễ dàng để làm cho nó đa luồng, mà sẽ cung cấp cho một khả năng mở rộng tuyến tính tốt đẹp.

+0

Vì vậy, bạn thông minh, huh? Tôi nghĩ đầu của bạn sẽ lớn hơn. :) – psihodelia

+0

+1 CC4FBB6A :-) –

+0

tốt, có vẻ như không ai đã trình bày bất kỳ câu trả lời đúng (cung cấp smth. Tốt hơn so với một lực lượng vũ phu), nhưng tôi sẽ cung cấp cho giọng nói của tôi với bạn bởi vì bạn có số cao nhất của upvotes; dù sao, cảm ơn bạn vì những nỗ lực của bạn! – psihodelia

1

Thiếu bất kỳ hướng dẫn cụ thể nào, tôi xác định tổng kiểm tra dữ liệu không tồn tại dưới dạng kiểm tra không tồn tại, vì vậy việc tạo tệp trống sẽ đáp ứng yêu cầu.

Một phương pháp điển hình khác là kiểm tra âm - tức là sau khi dữ liệu bạn viết một giá trị làm cho tổng kiểm tra của toàn bộ tệp (bao gồm cả tổng kiểm tra) xuất hiện bằng không. Trong trường hợp này, bạn viết tổng kiểm tra là 0 và tất cả đều hoạt động.

+0

Tôi đã chỉ định CRC-32 – psihodelia

+0

Kiểm tra chính xác mà bạn sử dụng là (chủ yếu) không liên quan - chủ yếu là về cách bạn áp dụng nó. –

10

Ngoài Jerry Coffin và câu trả lời tốt Esko Luontola của một vấn đề không bình thường, tôi muốn thêm:

Về mặt toán học, chúng tôi đang tìm kiếm X như vậy F (X) = X, trong đó F là chức năng kiểm tra, và X là chính dữ liệu. Vì đầu ra của tổng kiểm tra có kích thước cố định và đầu vào chúng tôi đang tìm kiếm có cùng kích thước, không có gì đảm bảo rằng X thậm chí tồn tại! Rất có thể là mọi giá trị đầu vào của kích thước cố định đều tương quan với một giá trị khác của kích thước đó.

CHỈNH SỬA: Câu hỏi của bạn không chỉ định chính xác cách kiểm tra được định dạng trong tệp, vì vậy tôi cho rằng bạn có nghĩa là biểu diễn byte của tổng kiểm tra. Khi các chuỗi và mã hóa và chuỗi định dạng đến để chơi, mọi thứ trở nên phức tạp hơn.

+1

Thực tế cho một thuật toán kiểm tra sẽ không bạn muốn đảm bảo rằng X! = F (X) để ngăn chặn toàn bộ một loạt các va chạm attacts –

+0

Không nếu bạn giả định rằng nó thực sự là dễ bị tổn thương hơn. Đây là điểm yếu lớn nhất trong Enigma nổi tiếng. Tại vì sợ rằng tôi có thể nói rằng đó là một cái gì đó sai nếu bạn có thể chứng minh rằng tài sản. –

+0

@ralu: giả sử tôi lấy hàm MD5 và xác định hàm băm mới để bao gồm tổng MD5 của đầu vào, trước bit 0 nếu bit đầu vào đầu tiên là 1 và 1 nếu là 0 Hàm băm có thể không có điểm cố định, và có thể "gần như" mạnh như MD5 (nếu biết bit đầu tiên của tin nhắn cho phép bạn crack MD5 trong thời gian X, bạn có thể crack nó mà không cần bit đầu tiên trong thời gian 2X). Vì vậy, tôi không nghĩ rằng sự tồn tại của một điểm cố định là một vấn đề. Enigma có một tài sản khá mạnh hơn là không có một điểm cố định: nó không bao giờ mã hóa ngay cả một nhân vật duy nhất cho chính nó. –

0

Đậy sức mạnh. CRC-32 cung cấp cho bạn một chuỗi có chiều dài 8 chứa chữ số và chữ cái của A-F (nói cách khác, đó là một số thập lục phân). Hãy thử mọi kết hợp, cung cấp cho bạn 16 = nhiều khả năng.Sau đó, băm từng khả năng và xem nó có cung cấp cho bạn chuỗi gốc hay không.

Bạn có thể thử tối ưu hóa bằng cách giả sử giải pháp sẽ sử dụng từng ký tự không quá hai hoặc ba lần, điều này có thể làm cho nó hoàn thành nhanh hơn.

Nếu bạn có quyền truy cập vào triển khai CRC32, bạn cũng có thể thử giải thuật toán và tìm giải pháp nhanh hơn nhiều, nhưng tôi không biết bạn sẽ làm như thế nào.

+0

"CRC-32 cung cấp cho bạn một chuỗi có chiều dài 8 chứa chữ số và chữ cái của A-F" - không, CRC32 trả về một số nguyên 32 bit. Nhiều chương trình đơn giản biểu diễn nó trong hệ thập lục phân. –

+0

bạn có thể thử cksum somefile.bin trong thiết bị đầu cuối của bạn, nó sẽ in một chuỗi, đại diện cho một số nguyên thập phân của loại integer32 – psihodelia

1

Lực lượng vũ phu. Đây là Adler32, mà tôi chưa từng thực hiện trước đây, và không bận tâm thử nghiệm, vì vậy nó khá có khả năng tôi đã làm hỏng nó lên. Tôi sẽ không mong đợi một phiên bản sửa chữa để chạy chậm hơn đáng kể, mặc dù, trừ khi tôi đã làm một cái gì đó khổng lồ sai.

này giả định rằng giá trị 32bit checksum được ghi vào tập tin ít về cuối nhỏ (tôi không tìm thấy một điểm cố định với nó lớn-endian):

#include <iostream> 
#include <stdint.h> 
#include <iomanip> 

const int modulus = 65521; 

void checkAllAdlers(uint32_t sofar, int depth, uint32_t a, uint32_t b) { 
    if (depth == 4) { 
     if ((b << 16) + a == sofar) { 
      std::cout << "Got a fixed point: 0x" << 
       std::hex << std::setw(8) << std::setfill('0') << 
       sofar << "\n"; 
     } 
     return; 
    } 
    for (uint32_t i = 0; i < 256; ++i) { 
     uint32_t newa = a + i; 
     if (newa >= modulus) newa -= modulus; 
     uint32_t newb = b + a; 
     if (newb >= modulus) newb -= modulus; 

     checkAllAdlers(sofar + (i << (depth*8)), depth + 1, newa, newb); 
    } 
    return; 
} 

int main() { 
    checkAllAdlers(0, 0, 1, 0); 
} 

Output:

$ g++  adler32fp.cpp -o adler32fp -O3 && time ./adler32fp 
Got a fixed point: 0x03fb01fe 

real 0m31.215s 
user 0m30.326s 
sys  0m0.015s 

[Chỉnh sửa: một số lỗi đã được sửa, tôi không có sự tự tin gì về tính chính xác của mã này ;-) Dù sao, bạn có ý tưởng: một kiểm tra 32 bit sử dụng mỗi byte đầu vào chỉ một lần rất rẻ. Checksums thường được thiết kế để nhanh chóng tính toán, trong khi băm thường chậm hơn nhiều, mặc dù chúng có tác dụng tương tự bề ngoài. Nếu checksum của bạn là "2 vòng của Adler32" (có nghĩa là tổng kiểm tra đích là kết quả của việc tính toán tổng kiểm tra và sau đó tính toán tổng kiểm tra của checksum đó) thì cách tiếp cận đệ quy của tôi sẽ không giúp được gì nhiều, phổ biến giữa các đầu vào với tiền tố chung. MD5 có 4 vòng, SHA-512 có 80.]

Các vấn đề liên quan