android – 相当于ios的spongycastle加密

这让我很难过 – 以下代码使用spongycastleAndroid加密/解密 – 我正在尝试为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 1000

PKCS12ParametersGenerator *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
>最初的字符串是快速的棕色狐狸跳过懒狗并跑开了

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


这篇“android轻量级无侵入式管理数据库自动升级组件怎么实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定...
今天小编给大家分享一下Android实现自定义圆形进度条的常用方法有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文...
这篇文章主要讲解了“Android如何解决字符对齐问题”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Android...
这篇文章主要介绍“Android岛屿数量算法怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Android岛屿数量算...
本篇内容主要讲解“Android如何开发MQTT协议的模型及通信”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Andro...
本文小编为大家详细介绍“Android数据压缩的方法是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Android数据压缩的方法是什么”文章能帮助大家解决疑惑...
这篇“Android怎么使用Intent传大数据”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅...
本文小编为大家详细介绍“Android事件冲突怎么解决悬浮窗拖拽问题”,内容详细,步骤清晰,细节处理妥当,希望这篇“Android事件冲突怎么解决悬浮窗拖拽问题”文...
这篇文章主要介绍了Android拼接如何实现动态对象的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Android拼接如何实现动态对象文...
今天小编给大家分享一下Android全面屏适配怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下...
本篇内容介绍了“Android怎么开发Input系统触摸事件分发”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何...
今天小编给大家分享一下AndroidRoom怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下...
本文小编为大家详细介绍“AndroidRoom使用方法有哪些”,内容详细,步骤清晰,细节处理妥当,希望这篇“AndroidRoom使用方法有哪些”文章能帮助大家...
这篇文章主要介绍“Android中的OpenGL怎么配置使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Android中的Open...
这篇文章主要介绍了Android如何自定义自动识别涂鸦工具类的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Android如何自定义自动...
今天小编给大家分享一下Android如何自定义有限制区域的图例角度自识别涂鸦工具类的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以...
今天小编给大家分享一下ReactNative错误采集原理在Android中如何实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章...
这篇文章主要讲解了“Android崩溃日志收集和保存代码分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“A...
这篇“Android面向单Activity开发实例分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大...
本篇内容介绍了“Android应用启动白屏处理的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何...