2010-04-15 37 views
14

Gần đây tôi đã chọn một bản sao của Mật mã ứng dụng của Bruce Schneier và nó đã được đọc tốt. Bây giờ tôi đã hiểu cách một số thuật toán được nêu trong tác phẩm sách và tôi muốn bắt đầu triển khai một số thuật toán trong C.Có gì xấu khi chuyển một biến 32 bit 32 bit?

Một điều mà nhiều thuật toán có chung là chia khóa x-bit thành một số phím y-bit nhỏ hơn. Ví dụ, khóa Blowfish, X, là 64 bit, nhưng bạn được yêu cầu chia nó thành hai nửa 32 bit; Xl và Xr.

Đây là nơi tôi bị kẹt. Tôi khá tốt với C, nhưng tôi không phải là mạnh nhất khi nói đến các nhà khai thác bitwise và muốn.

Sau khi một số giúp đỡ về IRC, tôi quản lý để đưa ra hai macro sau đây:

#define splitup(a, b, c) {b = a >> 32; c = a & 0xffffffff; } 
#define combine(a, b, c) {a = (c << 32) | a;} 

Trường hợp là 64 bit và b và c là 32 bit. Tuy nhiên, trình biên dịch cảnh báo tôi về thực tế là tôi đang chuyển một biến 32 bit 32 bit.

Câu hỏi của tôi là những:

  • gì xấu về chuyển một 32-bit biến 32 bit? Tôi đoán nó không xác định, nhưng các macro này dường như đang hoạt động.
  • Ngoài ra, bạn có đề xuất tôi nên thực hiện theo cách này không?

Như tôi đã nói, tôi khá quen thuộc với C, nhưng các nhà khai thác bitwise và những thứ tương tự vẫn khiến tôi đau đầu.

EDIT

tôi đã tìm ra rằng kết hợp vĩ mô của tôi đã không thực sự kết hợp hai biến 32-bit, mà chỉ đơn giản ORing 0 bởi một, và nhận được một kết quả là.
Vì vậy, trên các câu hỏi trước của tôi, tôi vẫn không có phương pháp kết hợp hai biến 32 bit để có được một biến 64 bit; một gợi ý về cách làm điều đó sẽ được đánh giá cao.

+4

+1, câu hỏi hay, cảm ơn bạn đã dành thời gian định dạng chính xác và chào mừng bạn đến với Stack Overflow! –

+0

Nhân tiện, tôi đặt cược macro kết hợp của bạn được cho là ORING với b chứ không phải a, phải không? – tloflin

Trả lời

18

Có, đó là hành vi không xác định.

ISO/IEC 9899: 1999 6.5.7 Bitwise nhà khai thác dịch chuyển ¶3

Các chương trình khuyến mãi số nguyên được thực hiện trên mỗi toán hạng. Loại kết quả là kết quả của toán hạng bên trái được quảng bá. Nếu giá trị của toán hạng bên phải là âm hoặc lớn hơn hoặc bằng với chiều rộng của toán hạng trái được thăng hạng, hành vi là không xác định.

C11 aka ISO/IEC 9899: 2011 cũng nói như vậy.

Trước tiên, bạn nên đúc b thành loại số nguyên mục tiêu. Một điểm khác là bạn nên đặt dấu ngoặc đơn xung quanh các tham số macro để tránh những điều bất ngờ bởi các toán tử ưu tiên. Ngoài ra, toán tử dấu phẩy rất hữu ích ở đây, cho phép bạn tránh các dấu ngoặc, để macro có thể được sử dụng như một lệnh bình thường, được đóng bằng một dấu chấm phẩy.

#define splitup(a,b,c) ((b) = (a) >> 32, (c) = (a) & 0xffffffff) 
#define combine(a,b,c) ((a) = ((unsigned long long)(b) << 32) | (c)) 

Có thể cần thêm các cảnh báo khác để tách cảnh báo mất chính xác bởi trình biên dịch quá hoang tưởng.

#define splitup(a,b,c) ((b) = (unsigned long)((a) >> 32), (c) = (unsigned long)((a) & 0xffffffff)) 

Và vui lòng thậm chí không nghĩ đến việc sử dụng mã hóa tự viết cho mã sản xuất.

3

điều gì xấu về việc chuyển một biến 32 bit 32 bit?

Tốt hơn là chỉ định 0 cho số nguyên n bit thay vì chuyển nó bằng n-bit.

Ví dụ:

0 0 1 0 1 ----- 5 bit Integer 
0 1 0 1 0 ----- 1st shift 
1 0 1 0 0 ----- 2nd shift 
0 1 0 0 0 ----- 3rd shift 
1 0 0 0 0 ----- 4th shift 
0 0 0 0 0 ----- 5th shift (all the bits are shifted!) 

tôi vẫn không có một phương pháp của việc kết hợp các biến hai 32-bit để có được một 64-bit một

Hãy xem xét:a là 64 bit, bc là 32 bit

a = b; 
a = a << 32; //Note: a is 64 bit 
a = a | c; 
+0

Ồ, được rồi. Vì vậy, macro kết hợp của tôi là ORing 0 bởi a để có được một; trong đó, nếu tôi đúng, có nghĩa là nó không thực sự kết hợp hai biến 32-bit để tạo một biến 64 bit. darn. – masseyc

0

Trừ khi đây là một số "phát minh lại bánh xe để hiểu cách hoạt động" dự án, không triển khai các chức năng mã hóa của riêng bạn.

Bao giờ hết. Thật khó để sử dụng các thuật toán có sẵn để làm việc (và để chọn đúng thuật toán), đừng bắn mình vào chân bằng cách đưa vào sản xuất một số API mã hóa được phát triển tại nhà. Rất có thể là your encryption won't encrypt

+3

Cảm ơn lời khuyên, nhưng điều này * là * một trong những "sáng tạo lại bánh xe để hiểu nó hoạt động như thế nào" các dự án. :) – masseyc

+0

OK, nhưng đừng quên phá hủy mã khi bạn hoàn thành: D – Guillaume

+3

Tôi không tin lời khuyên này. – Joshua

10

Chuyển giá trị 32 bit xuống 32 bit trở lên không được xác định trong C và C++. Một trong những lý do nó không được xác định là trên một số nền tảng phần cứng, lệnh chuyển đổi 32 bit chỉ tính đến 5 bit thấp nhất của số lần dịch chuyển được cung cấp. Điều này có nghĩa là bất kỳ số lần thay đổi nào bạn vượt qua, nó sẽ được giải thích modulo 32. Cố gắng thay đổi 32 trên nền tảng như vậy sẽ thực sự thay đổi bằng 0, tức là không thay đổi chút nào.

Tác giả ngôn ngữ không muốn gánh nặng các trình biên dịch được viết cho nền tảng như vậy với nhiệm vụ phân tích số lần dịch chuyển trước khi thực hiện ca làm việc. Thay vào đó, đặc tả ngôn ngữ nói rằng hành vi là không xác định. Điều này có nghĩa rằng nếu bạn muốn nhận được giá trị 0 từ một sự thay đổi 32 bit bằng 32 (hoặc nhiều hơn), bạn có thể nhận ra tình huống và xử lý nó theo đó.

+6

Nó có lẽ là giá trị chỉ ra rằng "một số nền tảng" trong trường hợp này bao gồm x86. – caf

+0

không thể tin được ... trình biên dịch nên "bù" cho kiến ​​trúc phần cứng cơ bản "giới hạn" ... nếu nó tồn tại một bộ xử lý không thực hiện bit shift (lẻ !!) thì sao? toàn bộ kết quả của >> hoặc << sẽ không được xác định ?! vui ... – ShinTakezou

+1

@ShinTakezou: Một số chương trình cần đánh giá 'x << (y & 31)'. Đôi khi các chương trình cần 'y> = 32? 0: x << y'. Một số sẽ không kém phần hạnh phúc với một trong hai kết quả. Nếu tiêu chuẩn bắt buộc hoặc là hành vi, sau đó trình biên dịch cho ít nhất một số nền tảng sẽ phải tạo ra mã không cần thiết cho các chương trình mà không quan tâm kết quả mà họ nhận được. Tồi tệ hơn, khi các chương trình cần kết quả ngược lại được chạy trên nền tảng "tự nhiên" trả về chương trình mong muốn, các lập trình viên sẽ phải viết mã để khắc phục các hiệu ứng của mã không mong muốn được trình biên dịch giới thiệu. – supercat

0

Có gì xấu khi chuyển một biến 32 bit 32 bit?

Ngoài những gì đã đã nói, các bit là bit dấu, và bạn có thể nhận được phần mở rộng dấu hiệu để bảo tồn hát, do đó mất bit có ý nghĩa.

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