2014-06-22 17 views
6

Tôi có ứng dụng khách/máy chủ đơn luồng cần thực hiện cả mã hóa và giải mã thông tin liên lạc mạng của họ. Tôi dự định sử dụng API EVP của OpenSSL và AES-256-CBC.Tôi có cần nhiều cấu trúc EVP_CIPHER_CTX không?

Một số giả mẫu mã tôi tìm thấy từ một vài ví dụ:

// key is 256 bits (32 bytes) when using EVP_aes_256_*() 
// I think iv is the same size as the block size, 128 bits (16 bytes)...is it? 
1: EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); 
2: EVP_CipherInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv, 1); //0=decrypt, 1=encrypt 
3: EVP_CipherUpdate(ctx, outbuf, &outlen, inbuf, inlen); 
4: EVP_CipherFinal_ex(ctx, outbuf + outlen, &tmplen)); 
5: outlen += tmplen; 
6: EVP_CIPHER_CTX_cleanup(ctx); 
7: EVP_CIPHER_CTX_free(ctx); 

Vấn đề là từ tất cả các ví dụ này, tôi không chắc chắn những gì cần phải được thực hiện tại mỗi mã hóa/giải mã, và những gì tôi chỉ nên làm một lần khi khởi động.

Cụ thể:

  • Tại dòng 1, để tôi tạo EVP_CIPHER_CTX này chỉ một lần và giữ lại sử dụng nó cho đến khi ứng dụng kết thúc?
  • Cũng tại dòng 1, tôi có thể sử dụng lại cùng một số EVP_CIPHER_CTX cho cả mã hóa và giải mã hay tôi có nên tạo 2 trong số đó không?
  • Tại dòng 2, IV có nên được đặt lại ở mọi gói tôi đang mã hóa không? Hay tôi đặt IV chỉ một lần, và sau đó để nó tiếp tục mãi mãi?
  • Nếu tôi mã hóa gói UDP, nơi gói tin có thể dễ dàng bị mất hoặc nhận được không đúng thứ tự: tôi có đúng khi nghĩ CBC sẽ không hoạt động hay đây là nơi tôi cần đặt lại IV khi bắt đầu của mỗi gói tôi gửi đi?
+3

Câu hỏi này dường như không có chủ đề vì đó là về việc sử dụng thư viện mật mã (ví dụ: Crypto ++, OpenSSL vv) và sử dụng nó trong ứng dụng của bạn. – otus

+0

Nếu crypto.stackexchange.com không thể được sử dụng để đặt câu hỏi cụ thể cho OpenSSL, thì quản trị viên có thể chuyển câu hỏi này sang stackoverflow thay thế không? –

+1

@ Stéphane Tôi vừa ping các mod để thông báo cho họ về [** yêu cầu di chuyển của bạn **] (http://crypto.stackexchange.com/questions/17828/openssl-do-i-need-multiple-evp-cipher- ctx-structure # comment39284_17828). (Nhân tiện: bạn luôn có thể “[flag”] (http://crypto.stackexchange.com/questions/17828/openssl-do-i-need-multiple-evp-cipher-ctx-structures#) ” câu hỏi riêng và chọn "khác (cần ♦ người điều hành)". Bằng cách đó, bạn có thể thông báo cho người kiểm duyệt rằng câu hỏi cần can thiệp/trợ giúp/v.v. Chỉ trong trường hợp bạn chưa biết thực tế đó ...) –

Trả lời

7

Tôi có ứng dụng khách/máy chủ đơn luồng cần thực hiện cả mã hóa và giải mã thông tin liên lạc mạng của họ. Tôi dự định sử dụng API EVP của OpenSSL và AES-256-CBC.

Nếu bạn đang sử dụng chức năng SSL_* từ libssl, sau đó bạn có thể sẽ không bao giờ chạm vào EVP_* API.


Tại dòng 1, cách nào để tạo EVP_CIPHER_CTX này chỉ một lần và giữ lại sử dụng nó cho đến khi ứng dụng kết thúc?

Bạn tạo một lần cho mỗi lần sử dụng. Đó là, khi bạn cần mã hóa, bạn sử dụng cùng một ngữ cảnh. Nếu bạn cần mã hóa luồng thứ hai, bạn sẽ sử dụng ngữ cảnh thứ hai. Nếu bạn cần giải mã luồng thứ ba, bạn sẽ sử dụng ngữ cảnh thứ ba.


Cũng tại dòng 1, tôi có thể tái sử dụng EVP_CIPHER_CTX tương tự cho cả hai mã hóa và giải mã, hay tôi phải tạo ra 2 trong số họ?

Không, xem ở trên.

Mật mã sẽ có các trạng thái khác nhau.


Tại dòng 2, nên IV được tái thiết lập tại mỗi gói tôi mã hóa? Hay tôi đặt IV chỉ một lần, và sau đó để nó tiếp tục mãi mãi?

No.Bạn đặt IV một lần và sau đó quên nó đi. Đó là một phần của trạng thái mà đối tượng bối cảnh quản lý cho mật mã.


gì nếu tôi mã hóa các gói tin UDP, nơi một gói tin có thể dễ dàng đi thiếu hoặc được nhận out-of-trật tự: Tôi thích hợp trong suy nghĩ CBC wont work ...

Nếu bạn đang sử dụng UDP, tùy thuộc vào bạn để phát hiện các loại sự cố này. Có thể bạn sẽ kết thúc việc phát minh lại TCP.

Mã hóa một mình thường không đủ. Bạn cũng cần phải đảm bảo tính xác thực và toàn vẹn. Bạn không hoạt động trên dữ liệu không xác thực. Đó là điều khiến cho SST/TLS và SSH gặp rắc rối.

Ví dụ, đây là anh chàng người viết seminal paper on authenticated encryption đối với IPSec, SSL/TLS và SSH nặng ở trên Authenticate-Rồi-Encrypt (ETA) chương trình được sử dụng bởi SSL/TLS với: Last Call: (Encrypt-then-MAC for TLS and DTLS) to Proposed Standard:

Các kết quả kỹ thuật trong bài báo 2001 của tôi là chính xác nhưng kết luận về SSL/TLS là sai. Tôi giả định rằng TLS đang sử dụng IV mới và rằng MAC được tính trên bản rõ được mã hóa, tức là Mã hóa-Mac-Mã hóa trong khi TLS đang thực hiện Mã hóa mã hóa Mac là chính xác ví dụ lý thuyết của tôi cho thấy không an toàn.

Để xác thực, bạn nên từ bỏ chế độ CBC và chuyển sang chế độ GCM. GCM là một chế độ mã hóa được xác thực, và nó kết hợp tính bảo mật và tính xác thực vào một chế độ để bạn không phải kết hợp các nguyên thủy (như AES/CBC với một HMAC).


hoặc là này mà tôi cần phải thiết lập lại IV vào lúc bắt đầu của mỗi gói tin tôi gửi ra?

Không, bạn đặt IV một lần rồi quên nó đi.


Vấn đề là từ tất cả các ví dụ này, tôi không chắc chắn những gì cần phải được thực hiện tại tất cả các mã hóa/giải mã, và những gì tôi chỉ nên làm một lần khi khởi động.

  1. Tạo điều này một lần: EVP_CIPHER_CTX
  2. Gọi này một lần cho thiết lập: EVP_CipherInit
  3. Gọi này nhiều lần như bạn muốn: EVP_CipherUpdate
  4. Gọi này một lần cho dọn dẹp: EVP_CipherFinal

Wiki OpenSSL có một vài ví dụ về cách sử dụng giao diện EVP_*. Xem EVP Symmetric Encryption and Decryption, EVP Authenticated Encryption and DecryptionEVP Signing and Verifying.

Tất cả các ví dụ sử dụng cùng một mẫu: Init, Update và sau đó Final. Nó không quan trọng nếu mã hóa hoặc băm của nó.


Có liên quan: bạn cần quan tâm: EVP Authenticated Encryption and Decryption. Mã mẫu của nó từ wiki OpenSSL.


Related: bạn có thể tìm các bản sao của Viega, Messier và Chandra's Network Security with OpenSSL trực tuyến. Bạn có thể xem xét tìm kiếm một bản sao và làm quen với một số khái niệm của nó.

+0

Đó là một số lời khuyên âm thanh và mở rộng, tôi sẽ đề nghị Stephane chấp nhận nó. –

+0

Ngữ cảnh evp là gì? Nó gây lỗi cho tôi rằng nó không bao giờ được định nghĩa hoặc giải thích một cách rõ ràng (ở bất cứ đâu, kể cả tài liệu). Câu trả lời tuyệt vời mặc dù. – LazerSharks

6

Xin lỗi vì làm sống lại một chủ đề cũ, nhưng tôi nhận thấy các lỗi sau trong câu trả lời được chấp nhận:

Tại dòng 1, cách nào để tạo EVP_CIPHER_CTX này chỉ một lần và giữ lại sử dụng nó cho đến khi ứng dụng kết thúc?

Bạn tạo một lần cho mỗi lần sử dụng. Đó là, khi bạn cần mã hóa, bạn sử dụng cùng một ngữ cảnh. Nếu bạn cần mã hóa luồng thứ hai, bạn sẽ sử dụng ngữ cảnh thứ hai. Nếu bạn cần giải mã luồng thứ ba, bạn sẽ sử dụng ngữ cảnh thứ ba.

Cũng ở dòng 1, tôi có thể sử dụng lại cùng một EVP_CIPHER_CTX cho cả mã hóa và giải mã hay tôi có nên tạo 2 trong số đó không?

Không, xem ở trên.

Điều này là không cần thiết. Từ trang người đàn ông cho OpenSSL:

Code mới nên sử dụng EVP_EncryptInit_ex(), EVP_EncryptFinal_ex(), EVP_DecryptInit_ex(), EVP_DecryptFinal_ex(), EVP_CipherInit_ex() và EVP_CipherFinal_ex() bởi vì họ có thể tái sử dụng một bối cảnh hiện tại mà không phân bổ và giải phóng nó lên trên mỗi cuộc gọi.

Nói cách khác, bạn cần phải khởi tạo lại ngữ cảnh mỗi lần trước khi sử dụng, nhưng bạn chắc chắn có thể sử dụng cùng một ngữ cảnh lặp đi lặp lại mà không cần tạo (phân bổ) cái mới.

+1

Ngữ cảnh evp là gì? Nó gây lỗi cho tôi rằng nó không bao giờ được định nghĩa hoặc giải thích một cách rõ ràng (ở bất cứ đâu, kể cả tài liệu). – LazerSharks

+0

Cảm ơn lời khuyên, đây là những gì tôi đã được tìm kiếm cho dù đó là "hợp pháp". Bằng cách chia sẻ một ngữ cảnh cho mỗi luồng ('EVP_CIPHER_CTX_new()'), nhưng chỉ khởi tạo lại nó cho mỗi chu kỳ giải mã ('EVP_DecryptInit_ex()'), tôi đã có thể tăng tốc độ của ứng dụng lên gần 5x! – Demonslay335

+0

Đây phải là câu trả lời đúng vì người dùng có thể sử dụng cùng một EVP_CIPHER_CTX cho nhiều chu kỳ mã hóa và giải mã nhiều lần. (Tôi đã thử nghiệm nó với chi nhánh 1.0.2) –

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