2016-12-02 254 views
2


我需要加密來實現++相當於BouncyCastle的的「ECIESwithAES-CBC /無/ PKCS7Padding」
ECIES與AES和CBC加密中++

主要原因是我需要在iOS上加密數據並在後端使用BouncyCastle在Java中解密它,我們希望使用這些特定的算法/配置。

我有零經驗與C++,但這裏是我走到這一步,在加密+:

// loaded private key 
const unsigned char* privateKey; 
size_t keyLength; 

AutoSeededRandomPool prng; 

ECIES_BC<ECP>::Decryptor decryptor; 
decryptor.AccessPrivateKey().Load(StringStore(privateKey, keyLength).Ref()); 
ECIES_BC<ECP>::Encryptor encryptor(decryptor); 

std::string plain("a"); // the message 
std::string cipher; 

SecByteBlock key(AES::DEFAULT_KEYLENGTH); 
prng.GenerateBlock(key, key.size()); 

byte iv[ AES::BLOCKSIZE ]; 
prng.GenerateBlock(iv, sizeof(iv)); 

CBC_Mode<AES>::Encryption e; 
e.SetKeyWithIV(key, key.size(), iv); 

StringSource ss1(plain, true, 
     new StreamTransformationFilter(e, 
       new StringSink(cipher), StreamTransformationFilter::PKCS_PADDING 
            ) // StreamTransformationFilter 
       ); // StringSource 


std::string cryptogram; 
StringSource ss2 (cipher, true, 
          new PK_EncryptorFilter(prng, encryptor, new StringSink(cryptogram))); 
// ... decrypt cryptogram in bouncy castle 

這裏是java部分:

private static final Provider SECURITY_PROVIDER = new BouncyCastleProvider(); 

public byte[] decryptMessage(byte[] message) throws Exception { 
    KeyFactory keyFactory = KeyFactory.getInstance("EC", SECURITY_PROVIDER); 
    PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(
      IOUtils.toByteArray(getClass().getResourceAsStream("/key.pkcs8"))); 
    PrivateKey privKey = keyFactory.generatePrivate(privSpec); 

    Cipher cipher = Cipher.getInstance("ECIESwithAES-CBC/NONE/PKCS5Padding", SECURITY_PROVIDER); 
    cipher.init(Cipher.DECRYPT_MODE, privKey); 
    byte[] result = cipher.doFinal(message); 
    return result; 
} 

目前,當我走從Crypto ++輸出並嘗試在BouncyCastle中解密它,它會拋出一個異常:

javax.crypto.BadPaddingException: pad block corrupted 
    at org.bouncycastle.jcajce.provider.asymmetric.ec.IESCipher.engineDoFinal(Unknown Source) 
    at javax.crypto.Cipher.doFinal(Cipher.java:2087) 
    ... 

我不確定這是真的填充問題,還是我在做一些完全錯誤的事情?

任何建議和幫助將不勝感激。
謝謝!

PS:我已經申請在CryptoWiki

回答

1

ECIES提到的充氣城堡補丁有幾個不同的加密方式,根據不同的標準被使用。目前,Crypto ++僅實現P1363 XOR方法(以下是從gfpcrypt.h)。這可能解釋了大部分例外情況。

爲了解決問題,我相信你有三個選擇。首先,你可以使用XOR方法,因爲Bouncy Castle和Crypto ++都有它。其次,您可以使用Jack Lloyd's Botan。 Botan和Crypto ++都試圖與Bouncy Castle一起努力促進互操作,但Botan有更多的加密方法。

三,Crypto ++需要添加與Bouncy Castle兼容的另一種加密方法。我想它會被稱爲DL_EncryptionAlgorithm_AES_CBC。我不知道該NoneAES-CBC/NONE/PKCS7Padding什麼。

Crypto ++會很高興地添加DL_EncryptionAlgorithm_AES_CBC。要添加它,我需要有人與具有Java/BC經驗的人一起工作。如果您有興趣,請聯繫我一個noloader,gmail賬號


關於「牡丹和加密+嘗試,努力促進互操作性與充氣城堡對齊」 ...事情對用戶一團糟。馬丁內斯,恩西納斯和阿維拉請注意:A Survey of the Elliptic Curve Integrated Encryption Scheme

...不可能實現與所有這些標準兼容的軟件版本,關於具體操作和允許的功能和算法的列表。

我可以指出無數的互操作問題的例子,從您的問題到比特幣和Zcash由於太多不兼容的選擇而使其協議標準化的問題。它會一直持續下去。


這些評論從gfpcrypt.h,並且可以在Crypto++ Manual for ECIES

//! \class DL_EncryptionAlgorithm_Xor 
//! \brief P1363 based XOR Encryption Method 
//! \tparam MAC MessageAuthenticationCode derived class used for MAC computation 
//! \tparam DHAES_MODE flag indicating DHAES mode 
//! \tparam LABEL_OCTETS flag indicating the label is octet count 
//! \details DL_EncryptionAlgorithm_Xor is based on an early P1363 draft, which itself appears to be based on an 
//! early Certicom SEC-1 draft (or an early SEC-1 draft was based on a P1363 draft). Crypto++ 4.2 used it in its Integrated 
//! Ecryption Schemes with <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=false</tt> and <tt>LABEL_OCTETS=true</tt>. 
//! \details If you need this method for Crypto++ 4.2 compatibility, then use the ECIES template class with 
//! <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=false</tt> and <tt>LABEL_OCTETS=true</tt>. 
//! \details If you need this method for Bouncy Castle 1.54 and Botan 1.11 compatibility, then use the ECIES template class with 
//! <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=ture</tt> and <tt>LABEL_OCTETS=false</tt>. 
//! \details Bouncy Castle 1.54 and Botan 1.11 compatibility are the default template parameters. 
//! \since Crypto++ 4.0 
template <class MAC, bool DHAES_MODE, bool LABEL_OCTETS=false> 
class DL_EncryptionAlgorithm_Xor : public DL_SymmetricEncryptionAlgorithm 
{ 
public: 

    bool ParameterSupported(const char *name) const {return strcmp(name, Name::EncodingParameters()) == 0;} 
    size_t GetSymmetricKeyLength(size_t plaintextLength) const 
     {return plaintextLength + static_cast<size_t>(MAC::DIGESTSIZE);} 
    size_t GetSymmetricCiphertextLength(size_t plaintextLength) const 
     {return plaintextLength + static_cast<size_t>(MAC::DIGESTSIZE);} 
    size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const 
     {return SaturatingSubtract(ciphertextLength, static_cast<size_t>(MAC::DIGESTSIZE));} 
    void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters) const 
    { 
     CRYPTOPP_UNUSED(rng); 
     const byte *cipherKey = NULL, *macKey = NULL; 
     if (DHAES_MODE) 
     { 
      macKey = key; 
      cipherKey = key + MAC::DEFAULT_KEYLENGTH; 
     } 
     else 
     { 
      cipherKey = key; 
      macKey = key + plaintextLength; 
     } 

     ConstByteArrayParameter encodingParameters; 
     parameters.GetValue(Name::EncodingParameters(), encodingParameters); 

     if (plaintextLength) // Coverity finding 
      xorbuf(ciphertext, plaintext, cipherKey, plaintextLength); 

     MAC mac(macKey); 
     mac.Update(ciphertext, plaintextLength); 
     mac.Update(encodingParameters.begin(), encodingParameters.size()); 
     if (DHAES_MODE) 
     { 
      byte L[8]; 
      PutWord(false, BIG_ENDIAN_ORDER, L, (LABEL_OCTETS ? word64(encodingParameters.size()) : 8 * word64(encodingParameters.size()))); 
      mac.Update(L, 8); 
     } 
     mac.Final(ciphertext + plaintextLength); 
    } 
    DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters) const 
    { 
     size_t plaintextLength = GetMaxSymmetricPlaintextLength(ciphertextLength); 
     const byte *cipherKey, *macKey; 
     if (DHAES_MODE) 
     { 
      macKey = key; 
      cipherKey = key + MAC::DEFAULT_KEYLENGTH; 
     } 
     else 
     { 
      cipherKey = key; 
      macKey = key + plaintextLength; 
     } 

     ConstByteArrayParameter encodingParameters; 
     parameters.GetValue(Name::EncodingParameters(), encodingParameters); 

     MAC mac(macKey); 
     mac.Update(ciphertext, plaintextLength); 
     mac.Update(encodingParameters.begin(), encodingParameters.size()); 
     if (DHAES_MODE) 
     { 
      byte L[8]; 
      PutWord(false, BIG_ENDIAN_ORDER, L, (LABEL_OCTETS ? word64(encodingParameters.size()) : 8 * word64(encodingParameters.size()))); 
      mac.Update(L, 8); 
     } 
     if (!mac.Verify(ciphertext + plaintextLength)) 
      return DecodingResult(); 

     if (plaintextLength) // Coverity finding 
      xorbuf(plaintext, ciphertext, cipherKey, plaintextLength); 

     return DecodingResult(plaintextLength); 
    } 
}; 
相關問題