2016-12-02 252 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); 
    } 
}; 
相关问题