2015-10-17 66 views
2

我正在研究客戶端 - 服務器安全協議,因爲密鑰必須發送到服務器,所以我需要使用Java中的RSA加密SecretKey以獲取HMAC摘要。加密有兩個階段;首先,我需要使用公共非對稱密鑰對對稱密鑰進行加密,然後使用私有非對稱密鑰加密該加密消息。用Java中的RSA加密SecretKey

爲此我生成SecretKey的是:

public SecretKey generate(){ 
KeyGenerator generator = KeyGenerator.getInstance("HMACSHA256"); 
k = generator.generateKey(); 
return k; 
} 

後來,我使用此代碼的任何字節數組使用公鑰加密:

public byte[] encryptPublic(PublicKey key, byte[] array){ 
Cipher cipher = Cipher.getInstance("RSA"); 
cipher.init(Cipher.ENCRYPT_MODE, key); 
byte[] encrypted = cipher.doFinal(array); 
return encrypted; 
} 

的加密與私人碼密鑰是相同的,但使用私鑰。

對於我使用的是1024位長的非對稱密鑰的RSA加密,所以我有兩個主要問題:

  1. 我怎樣才能把我的SecretKey的字節數組,以便將它與RSA和公開加密鍵?
  2. 由於公鑰加密產生128字節的字節數組,如果密鑰長度爲1024位,並且只能加密117字節長的消息,如何使用私鑰再次加密該消息?
+2

一些評論。 1)不要在任何地方使用密碼學中的默認值。在你的'getInstance()'方法中,總是指定完整的三部分轉換字符串。 2)。不要使用私鑰進行加密,而是執行*簽署*。你使用'Signature'類。 3)密鑰,包括SecretKeys,有'getEncoded()'方法返回一個字節數組,代表某種標準格式的密鑰。對於對稱密鑰,即'SecretKey'實例,'getEncoded()'返回的字節數組就是原始密鑰字節。 –

+0

對於Q2:您可以使用隨機AES密鑰加密密文,然後使用另一輪RSA加密新的AES密鑰,但您爲什麼要這樣做? –

回答

2
  1. 如何將我的SecretKey轉換爲字節數組以便使用RSA和公鑰加密它?

這就是所謂的包裝:

public static byte[] wrapKey(PublicKey pubKey, SecretKey symKey) 
     throws InvalidKeyException, IllegalBlockSizeException { 
    try { 
     final Cipher cipher = Cipher 
       .getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding"); 
     cipher.init(Cipher.WRAP_MODE, pubKey); 
     final byte[] wrapped = cipher.wrap(symKey); 
     return wrapped; 
    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { 
     throw new IllegalStateException(
       "Java runtime does not support RSA/ECB/OAEPWithSHA1AndMGF1Padding", 
       e); 
    } 
} 

注意,這明確地不能轉換爲byte[]第一。這是因爲密鑰可能在例如一個硬件安全模塊。在HSM中,包裝可能是,但在本地存儲器中轉換爲byte[]通常是不可能的。


  • 作爲公開密鑰加密產生具有128個字節的字節數組,我怎樣才能再次加密該消息用私鑰如果密鑰是1024位長,並且僅可以加密一個117字節長的消息?
  • 你不應該這樣做,你也不能這樣做。原因是你不應該這樣做,因爲用私鑰加密不會提供機密性,因爲任何人都可以訪問公鑰。

    需要填充以執行安全的RSA加密。填充開銷(PKCS#1 v1.5樣式填充爲11字節)會阻止您使用私鑰進行加密。

    請注意,整個操作:使用私鑰加密甚至沒有在PKCS#1中指定 - 這不是合法操作。


    通常更安全短暫的,短暫的(EC)DH被用於建立傳輸協議按鍵,僅使用驗證的私鑰(S)。您可能想從TLS 1.3的(草稿版本)中獲得提示。或者您可能只想使用TLS或它的握手部分。