2009-09-17 57 views
16

Tôi đã đọc các chủ đề sau và chúng đã giúp một chút, nhưng tôi đang tìm thêm một chút thông tin.Cách triển khai mã hóa AES Java 256 bit với CBC

How to write AES/CBC/PKCS5Padding encryption and decryption with Initialization Vector Parameter for BlackBerry

Java 256bit AES Encryption

Về cơ bản, những gì tôi đang làm là viết một chương trình sẽ mã hóa một yêu cầu được gửi qua giao thức TCP/IP, và sau đó giải mã bởi một chương trình máy chủ. Mã hóa sẽ cần phải là AES, và làm một số nghiên cứu tôi phát hiện ra tôi cần phải sử dụng CBC và PKCS5Padding. Vì vậy, về cơ bản tôi cần một khóa bí mật và một IV là tốt.

Ứng dụng tôi đang phát triển là dành cho điện thoại, vì vậy tôi muốn sử dụng các gói bảo mật java để giảm kích thước. Tôi đã hoàn thành thiết kế, nhưng không chắc chắn về việc triển khai IV và khóa chia sẻ.

Dưới đây là một số mã:

// My user name 
byte[] loginId = "login".getBytes(); 

byte[] preSharedKey128 = "ACME-1234AC".getBytes(); 
byte[] preSharedKey192 = "ACME-1234ACME-1234A".getBytes(); 
// 256 bit key 
byte[] preSharedKey256 = "ACME-1234ACME-1234ACME-1234".getBytes(); 
byte[] preSharedKey = preSharedKey256; 

// Initialization Vector 
// Required for CBC 
byte[] iv ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
IvParameterSpec ips = new IvParameterSpec(iv); 


byte[] encodedKey = new byte[loginId.length + preSharedKey.length]; 

System.arraycopy(loginId, 0, encodedKey, 0, loginId.length); 
System.arraycopy(preSharedKey, 0, encodedKey, loginId.length, preSharedKey.length); 

// The SecretKeySpec provides a mechanism for application-specific generation 
// of cryptography keys for consumption by the Java Crypto classes. 

// Create a key specification first, based on our key input. 
SecretKey aesKey = new SecretKeySpec(encodedKey, "AES"); 

// Create a Cipher for encrypting the data using the key we created. 
Cipher encryptCipher; 

encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
// Initialize the Cipher with key and parameters 
encryptCipher.init(Cipher.ENCRYPT_MODE, aesKey, ips); 

// Our cleartext 
String clearString = "33,8244000,9999,411,5012022517,0.00,0,1,V330"; 
byte[] cleartext = clearString.getBytes(); 

// Encrypt the cleartext 
byte[] ciphertext = encryptCipher.doFinal(cleartext); 

// Now decrypt back again... 
// Decryption cipher 
Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
// Initialize PBE Cipher with key and parameters 
decryptCipher.init(Cipher.DECRYPT_MODE, aesKey, ips); 

// Decrypt the cleartext 
byte[] deciphertext = decryptCipher.doFinal(ciphertext); 

Tóm lại những gì nó nên làm là mã hóa một số thông điệp rằng có thể giải mã bởi các máy chủ mà không có máy chủ cần phải có được một chìa khóa hoặc IV từ điện thoại. Có cách nào tôi có thể làm điều này, nơi tôi có thể an toàn IV và chìa khóa trên điện thoại, và vẫn còn có chìa khóa và IV được biết đến bởi máy chủ là tốt? Cảm thấy tự do để nói với tôi để làm cho mọi thứ rõ ràng hơn nếu họ không.

+1

Khóa và mật mã được mã hóa ở đây chỉ dành cho sự hiểu biết của tôi. Tôi không biết nhiều về mã hóa nên tôi về cơ bản ở chế độ biên dịch và chạy. – Stevus

+1

Mô hình mối đe dọa của bạn là gì? Ý tôi là, nếu bạn đang nghĩ rằng mã hóa là cần thiết, bạn phải có một số ý tưởng về những người muốn thông tin này và tại sao, bao nhiêu họ nhận được nó sẽ làm tổn thương bạn, lợi ích cho họ, vv – erickson

+0

Tôi đoán mô hình mối đe dọa của tôi là chúng tôi có thông tin tài khoản/thông tin đăng nhập cần thiết để thực hiện giao dịch ngân hàng và chúng tôi không muốn bị lộ. Đó là những gì bạn đang tìm kiếm? – Stevus

Trả lời

11

Có một số vấn đề với mã. Trước hết, bạn thực sự nên sử dụng trình tạo khóa để tạo khóa bí mật. Chỉ cần sử dụng một số văn bản trực tiếp có thể làm việc cho một số thuật toán, nhưng những người khác có các phím yếu và vv mà cần phải được kiểm tra.

Thậm chí nếu bạn muốn thực hiện mã hóa dựa trên mật khẩu, mật khẩu sẽ được chạy thông qua thuật toán khóa để tạo khóa, như được hiển thị trong my answer cho câu hỏi mà bạn đã trích dẫn.

Ngoài ra, bạn không nên sử dụng phương pháp no-arg getBytes() của String. Đây là nền tảng phụ thuộc. Nếu tất cả các chuỗi mà bạn đang mã hóa chỉ chứa các ký tự từ bộ ký tự US-ASCII, hãy làm rõ bằng cách chỉ định mã hóa rõ ràng. Nếu không, nếu nền tảng điện thoại và máy chủ sử dụng các mã hóa ký tự khác nhau, khóa và IV sẽ không bật ra.

Đối với chế độ CBC, tốt nhất bạn nên sử dụng IV mới cho mọi thư bạn gửi. Thông thường, CBC IV được tạo ngẫu nhiên. Các chế độ khác như CFB và OFB yêu cầu IV duy nhất cho mọi thư. IV thường được gửi cùng với bản mã — IV không cần phải được giữ bí mật, nhưng nhiều thuật toán sẽ phá vỡ nếu một IV dự đoán được sử dụng.

Máy chủ không cần lấy bí mật hoặc IV trực tiếp từ điện thoại. Bạn có thể định cấu hình máy chủ bằng khóa bí mật (hoặc mật khẩu, từ đó khóa bí mật bắt nguồn), nhưng trong nhiều ứng dụng, đây sẽ là thiết kế tồi.

Ví dụ: nếu ứng dụng sẽ được triển khai cho điện thoại của nhiều người, bạn không nên sử dụng cùng một khóa bí mật. Một người dùng độc hại có thể khôi phục khóa và phá vỡ hệ thống cho mọi người.

Cách tiếp cận tốt hơn là tạo khóa bí mật mới trên điện thoại và sử dụng thuật toán thỏa thuận chính để trao đổi khóa với máy chủ. Thỏa thuận khóa Diffie-Hellman có thể được sử dụng cho điều này, hoặc khóa bí mật có thể được mã hóa bằng RSA và được gửi đến máy chủ.


Cập nhật:

Diffie-Hellman trong chế độ "phù du-tĩnh" (và chế độ "tĩnh tĩnh" quá, mặc dù đó là kém hấp dẫn) có thể không có một thông báo ban đầu từ các máy chủ để điện thoại, miễn là khóa công khai của máy chủ được nhúng trong ứng dụng.

Khóa công khai của máy chủ không gây rủi ro tương tự như nhúng khóa bí mật chung trong điện thoại. Vì nó là một khóa công khai, mối đe dọa sẽ là một kẻ tấn công nhận được bàn tay của mình (hoặc hack từ xa vào) điện thoại và thay thế khóa công khai thực sự bằng một khóa giả cho phép anh ta mạo danh máy chủ.

Chế độ tĩnh tĩnh có thể được sử dụng, nhưng nó thực sự phức tạp hơn và kém an toàn hơn một chút. Mỗi điện thoại sẽ cần cặp khóa duy nhất của riêng nó hoặc bạn rơi vào vấn đề về khóa bí mật. Ít nhất sẽ không cần máy chủ theo dõi điện thoại nào có khóa nào (giả sử có một số cơ chế xác thực ở cấp ứng dụng, như mật khẩu).

Tôi không biết điện thoại nhanh như thế nào. Trên máy tính để bàn của tôi, việc tạo ra cặp khóa tạm thời mất khoảng 1/3 giây. Việc tạo các tham số Diffie-Hellman rất chậm; bạn chắc chắn muốn sử dụng lại các tham số từ khóa máy chủ.

+0

Ngay bây giờ, thiết kế tôi đang được bảo sử dụng nói rằng chúng tôi có thể sử dụng cùng một khóa cho mọi điện thoại nhưng không đồng ý với nó. Cách tiếp cận Diffie-Hellman có dễ thực hiện không? – Stevus

+0

Không, Diffie-Hellman hơi khó hiểu, với tôi ít nhất. Nó sử dụng lớp KeyAgreement. Mã hóa RSA dễ dàng hơn. Nó sử dụng một mật mã như mã hóa AES bạn đang sử dụng. Một điều cần lưu ý với RSA là bản mã sẽ là hàng trăm byte, đó là một chút lãng phí nếu bản rõ của bạn chỉ là một vài byte; không chắc liệu điều đó có quan trọng trong ứng dụng của bạn hay không. Một tùy chọn khác để xem xét là nếu giao tiếp là thông điệp rất ngắn (100 đến 200 byte) từ điện thoại đến máy chủ chỉ, bạn chỉ có thể mã hóa thông điệp với RSA. – erickson

+0

Tôi nghĩ mức độ bảo mật mà tôi đang tìm kiếm không liên quan đến điều gì đó thực sự phức tạp. Tuy nhiên, hãy ghi nhớ điều đó. – Stevus

2

Xong dự án tương tự trong một MIDlet trước đây, tôi đã theo lời khuyên dành cho bạn:

  1. Không có cách nào an toàn để lưu trữ bí mật được chia sẻ trên điện thoại. Bạn có thể sử dụng nó nhưng điều này rơi vào một loại được gọi là Security through Obscurity. Nó giống như một loại bảo mật "chìa khóa".
  2. Không sử dụng AES 256 bit, không có sẵn rộng rãi. Bạn có thể phải cài đặt một JCE khác. 128-bit AES hoặc TripleDES vẫn được coi là an toàn. Xem xét # 1, bạn không nên lo lắng về điều này.
  3. Mã hóa bằng mật khẩu (khác nhau cho mỗi người dùng) an toàn hơn nhiều. Nhưng bạn không nên sử dụng mật khẩu làm khóa như bạn đang hiển thị trong ví dụ. Vui lòng sử dụng PBEKeySpec (mã hóa dựa trên mật khẩu) để tạo khóa.
  4. Nếu bạn chỉ lo lắng về các cuộc tấn công của MITM (man-in-the-middle), hãy sử dụng SSL.
+0

Tại sao không thể sử dụng AES 256 bit? Tôi đã có thể tạo một khóa 256-bit trong thiết lập thử nghiệm của mình, nhưng nó được thực hiện thủ công. Chủ yếu là, quản lý lo lắng về việc ai đó chặn việc truyền tải và sử dụng thông tin trong quá trình truyền hoặc nhận điện thoại và kỹ thuật đảo ngược thuật toán và về cơ bản là kẻ mạo danh trong mạng của chúng tôi. – Stevus

+0

Rất nhiều điện thoại chúng tôi đã thử không hỗ trợ. AES 128 bit vẫn được ngân hàng của tôi sử dụng. Nó an toàn. –

+1

Trên thực tế một số điểm yếu đã được tìm thấy trong AES 256. AES-128 là rất nhiều mạnh mẽ, và được khuyến cáo bởi Bruce Schneier trên AES 256 khi nó không cần thiết cho khả năng tương tác. (http://www.schneier.com/blog/archives/2009/07/another_new_aes.html) Tuy nhiên, thuật toán thực sự không quan trọng nếu khóa không an toàn. – erickson

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