android– 相当于ios的spongycastle加密

android– 相当于ios的spongycastle加密,第1张

概述这让我很难过 - 以下代码使用SpongyCastle的Android加密/解密 - 我正在尝试为iOS实现跨平台加密/解密.下面的代码(来自Android)使用PKCS7Padding处理AES 128bit CBC,使用提供的salt和密码,salt存储在mysql数据库中,密码由最终用户提供,以下代码改编自此回答kelhoer.我之所以使用AES128

这让我很难过 – 以下代码使用spongycastle的Android加密/解密 – 我正在尝试为iOS实现跨平台加密/解密.

下面的代码(来自AndroID)使用PKCS7padding处理AES 128bit CBC,使用提供的salt和密码,salt存储在MysqL数据库中,密码由最终用户提供,以下代码改编自此回答kelhoer.

我之所以使用AES128bit是因为AES256在iOS 4中不可用,它是在iOS5中引入的,并且不得不使用openssl来生成派生密钥和初始化向量(iv),因为学到苹果拒绝它是很冒险的与openssl库静态链接的应用程序.

由于该平台基于iOS 4.2,使用bundling and statically linking the openssl库似乎相当,过度杀死并且最好使用CommonCryptor库.

这是使用spongycastle代码的AndroID版本:

private static voID encrypt(inputStream fin,OutputStream fout,String password,byte[] bSalt) {    try {        PKCS12ParametersGenerator pGen = new PKCS12ParametersGenerator(            new SHA256Digest()            );        char[] passwordChars = password.tochararray();        final byte[] pkcs12PasswordBytes =             PBEParametersGenerator.PKCS12PasswordToBytes(passwordChars);        pGen.init(pkcs12PasswordBytes,bSalt,IteraTIONS);        CBCBlockCipher aesCBC = new CBCBlockCipher(new AESEngine());        ParametersWithIV aesCBCParams =             (ParametersWithIV) pGen.generateDerivedParameters(128,128);        aesCBC.init(true,aesCBCParams);        PaddedBufferedBlockCipher aesCipher =             new PaddedBufferedBlockCipher(aesCBC,new PKCS7padding());        aesCipher.init(true,aesCBCParams);        byte[] buf = new byte[BUF_SIZE];        // Read in the decrypted bytes and write the cleartext to out        int numRead = 0;        while ((numRead = fin.read(buf)) >= 0) {            if (numRead == 1024) {                byte[] plainTemp = new byte[                    aesCipher.getUpdateOutputSize(numRead)];                int offset =                     aesCipher.processBytes(buf,numRead,plainTemp,0);                final byte[] plain = new byte[offset];                System.arraycopy(plainTemp,plain,plain.length);                fout.write(plain,plain.length);            } else {                byte[] plainTemp = new byte[aesCipher.getoutputSize(numRead)];                int offset =                     aesCipher.processBytes(buf,0);                int last = aesCipher.doFinal(plainTemp,offset);                final byte[] plain = new byte[offset + last];                System.arraycopy(plainTemp,plain.length);            }        }        fout.close();        fin.close();    } catch (Exception e) {        e.printstacktrace();    }}private static voID decrypt(inputStream fin,128);        aesCBC.init(false,new PKCS7padding());        aesCipher.init(false,0);                // int last = aesCipher.doFinal(plainTemp,offset);                final byte[] plain = new byte[offset];                System.arraycopy(plainTemp,plain.length);            } else {                byte[] plainTemp = new byte[                    aesCipher.getoutputSize(numRead)];                int offset =                     aesCipher.processBytes(buf,plain.length);            }        }        fout.close();        fin.close();    } catch (Exception e) {        e.printstacktrace();    }}

但是在iOS 4.2(使用XCode)下我无法弄清楚如何做等效的,

这就是我在Objective C下尝试过的,其目标是解密来自AndroID端的数据,存储在MysqL数据库中,以测试它:

+(NSData*) decrypt:(NSData*)cipherData     userPassword:(Nsstring*)argPassword     genSalt:(NSData*)argPtrSalt{    size_t szPlainBufLen = cipherData.length + (kCCBlockSizeAES128);    uint8_t *ptrPlainBuf = malloc(szPlainBufLen);    //    const unsigned char *ptrPasswd =         (const unsigned char*)[argPassword             cStringUsingEnCoding:NSASCIIStringEnCoding];    int ptrPasswdLen = strlen(ptrPasswd);    //    Nsstring *ptrSaltStr = [[Nsstring alloc]        initWithData:argPtrSalt         enCoding:NSASCIIStringEnCoding];    const unsigned char *ptrSalt =         (const unsigned char *)[ptrSaltStr UTF8String];    Nsstring *ptrCipherStr =         [[Nsstring alloc]initWithData:cipherData             enCoding:NSASCIIStringEnCoding];    unsigned char *ptrCipher = (unsigned char *)[ptrCipherStr UTF8String];    unsigned char key[kCCKeySizeAES128];    unsigned char iv[kCCKeySizeAES128];    //    //int     EVP_BytesToKey(const EVP_CIPHER *type,const EVP_MD *md,//const unsigned char *salt,const unsigned char *data,//int datal,int count,unsigned char *key,unsigned char *iv);    int i = EVP_BytesToKey(EVP_aes_128_cbc(),EVP_sha256(),ptrSalt,ptrPasswd,ptrPasswdLen,PBKDF2_IteraTIONS,key,iv);    NSAssert(i == kCCKeySizeAES128,@"Unable to generate key for AES");    //    size_t cipherLen = [cipherData length];    size_t outlength = 0;    //    CCCryptorStatus resultCCStatus = CCCrypt(kCCDecrypt,kCCAlgorithmAES128,kCcoptionPKCS7padding,kCCBlockSizeAES128,iv,ptrCipher,cipherLen,ptrPlainBuf,szPlainBufLen,&outlength);    NSAssert(resultCCStatus == kCCSuccess,@"Unable to perform PBE AES128bit decryption: %d",errno);    NSData *ns_dta_PlainData = nil;    if (resultCCStatus == kCCSuccess){        ns_dta_PlainData =         [NSData dataWithBytesNocopy:ptrPlainBuf length:outlength];    }else{        return nil;    }    return ns_dta_PlainData;}

提供了数据和用户密码,并从CCCrypt获得返回码为-4304,表示解码不成功和错误.

我原以为编码方案可能会抛弃CommonCryptor的解密路由,因此转换为NSASCIIStringEnCoding的方法很冗长.

Salt与密码数据一起存储,长度为32字节.

考虑到密码学方面的问题,我在这方面缺少什么.

最佳答案我已经冒昧地编写了AndroID端口上使用的PKCS12Parameters generator的直接端口,这个标题的要点就在上面.

实现也是直接复制,如发现here,密码,转换为PKCS12等效 – unicode,big-endian,最后填充两个额外的零.

Generator通过执行迭代次数生成派生密钥,在本例中为1000,如在AndroID端,使用SHA256摘要,最终生成的密钥和iv然后用作CCCryptorCreate的参数.

使用以下代码示例也不起作用,它在调用CCCryptorFinal时以-4304结束

代码摘录如下所示:

#define IteraTIONS 1000PKCS12ParametersGenerator *pGen = [[PKCS12ParametersGenerator alloc]        init:argPassword         saltedHash:argPtrSalt         iterCount:IteraTIONS         keySize:128         initVectSize:128]; //[pGen generateDerivedParameters];//CCCryptorRef decryptor = NulL;// Create and Initialize the crypto reference.CCCryptorStatus ccStatus = CCCryptorCreate(kCCDecrypt,pGen.derivedKey.bytes,kCCKeySizeAES128,pGen.derivediv.bytes,&decryptor                           );NSAssert(ccStatus == kCCSuccess,@"Unable to initialise decryptor!");//size_t szPlainBufLen = cipherData.length + (kCCBlockSizeAES128);// Calculate byte block alignment for all calls through to and including final.size_t szPtrPlainBufSize = CCCryptorGetoutputLength(decryptor,true);uint8_t *ptrPlainBuf = calloc(szPtrPlainBufSize,sizeof(uint8_t));//// Set up initial size.size_t remainingBytes = szPtrPlainBufSize;uint8_t *ptr = ptrPlainBuf;size_t movedBytes = 0;size_t totalBytesWritten = 0;// Actually perform the encryption or decryption.ccStatus = CCCryptorUpdate(decryptor,(const voID *) cipherData.bytes,szPtrPlainBufSize,ptr,remainingBytes,&movedBytes                           );NSAssert(ccStatus == kCCSuccess,@"Unable to update decryptor! Error: %d",ccStatus);ptr += movedBytes;remainingBytes -= movedBytes;totalBytesWritten += movedBytes;//// Finalize everything to the output buffer.CCCryptorStatus resultCCStatus = CCCryptorFinal(decryptor,&movedBytes                          );totalBytesWritten += movedBytes;if(decryptor) {    (voID) CCCryptorRelease(decryptor);    decryptor = NulL;}NSAssert(resultCCStatus == kCCSuccess,resultCCStatus);

有趣的是,解密工作,对CCCryptorFinal的最后调用返回0,如果我在CCCryptorCreate的开头用kCcoptionPKCS7padding代替0x0000,即没有填充.唉,这些数据并不是我所期望的,无论什么时候“不起作用”,它仍然是完全混乱的.

它在某个地方失败了,所以如果有人对如何实现等价物有任何更好的想法,我会很高兴听到其他意见.

要么改变AndroID方面的机制,使其与iPhone“跨平台”兼容,要么寻求替代的加密解决方案,在两端兼容,代价是用于使数据交换便携的平台两侧的加密能力较弱.

提供的输入数据:

> Base64编码密码,盐和密码用’:’分隔:tnNhKyJ2vvrUzAmtQV5q9uEwzzAH63sTKtLf4pOQylw =:qTBluA aNeFnEUfkUFUEVgNYrdz7enn5W1n4Q9uBKYmFfJeSCcbsfzIErsa4EU9Cz / pO0KE4WE1QdqRcvSXthQ ==
>提供的密码是f00b4r
>最初的字符串是快速的棕色狐狸跳过懒狗并跑开了 总结

以上是内存溢出为你收集整理的android – 相当于ios的spongycastle加密全部内容,希望文章能够帮你解决android – 相当于ios的spongycastle加密所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1140249.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存