Android上的AES解密太慢而无法使用 NDK会更快吗?还有其他想法吗?

问题描述

| 我已经使用内置的Cipher类在Android上实现了AES / CTR。出于我的目的,解密似乎太慢了,一个128KB的块在模拟器上需要大约6秒钟来解密,而在Samsung Galaxy硬件上则需要2.6秒。 我想知道使用NDK构建OpenSSL并调用其方法是否会更快。有人对这个有经验么?我的一部分希望相信Cipher(\“ AES / CTR / NoPadding \”)方法无论如何都是对本地OpenSSL调用的包装,因为支持Android的Linux OS应该安装libcrypto。如果真是这样,那么尝试使用NDK只是浪费时间,因为无法预期会有性能提升。 我没有在iOS上花时间,但即使3G硬件也是如此快速地解密,最终用户似乎可以立即进行10MB的解密。我发现很难相信Android的实现确实差了几个数量级,但这也许是现实。 如果这确实是我所面对的,是否有人对其他实施策略有任何想法,这些策略将为最终用户提供无法感知的响应(针对10Mb文件)?我办公室的另一位开发人员以嘲讽的方式建议我只使用XOR加密,这使我想面对自己,但我认为(除了安全方面的考虑),如果我这样做会起作用。 谢谢! 这是一些简化的代码供参考:
public class ResourceDecryptor {
    private static ThreadLocal<Cipher>      mCipher;
    private byte[]                          mIV = new byte[ 8 ];
    private SecretKeySpec                   mKey;
    private String                          mResourcePath;

    private static final int                kAESBlockSize = 16;

    public ResourceDecryptor( String resourcePath,String decryptionKey ) throws UnsupportedOperationException {
        // initialization of mKey,mIV,& mResourcePath,elided 

        // store mCipher as a thread local because Cipher.getInstance() is so slow,// ResourceDecryptor is a static object that persists for the app lifetime
        // so this leak is intentional and ok.
        mCipher = new ThreadLocal<Cipher>() {
            protected Cipher initialValue() {
                try { return Cipher.getInstance( \"AES/CTR/NoPadding\" ); } catch ( Exception e ) { }

                return null;
            }
        };
    }

    public ByteBuffer read( long offset,int length ) throws GeneralSecurityException,IOException {
        Cipher                      cipher;
        byte[]                      data,iv;
        FileInputStream             input;
        int                         prefix,readLength;

        input = null;
        prefix = (int)( offset % kAESBlockSize );
        readLength = ( prefix + length + kAESBlockSize - 1 ) / kAESBlockSize * kAESBlockSize;
        data = new byte[ readLength ];
        iv = new byte[ 16 ];

        try {
            input = new FileInputStream( mResourcePath );
            input.skip( offset -= prefix );

            if ( input.read( data ) != readLength ) throw new IOException( \"I/O error: unable to read \" + readLength + \" bytes from offset \" + offset );

            System.arraycopy( mIV,iv,8 );

            offset /= kAESBlockSize;

            iv[  8 ] = (byte)( offset >> 56 & 0xff );
            iv[  9 ] = (byte)( offset >> 48 & 0xff );
            iv[ 10 ] = (byte)( offset >> 40 & 0xff );
            iv[ 11 ] = (byte)( offset >> 32 & 0xff );
            iv[ 12 ] = (byte)( offset >> 24 & 0xff );
            iv[ 13 ] = (byte)( offset >> 16 & 0xff );
            iv[ 14 ] = (byte)( offset >>  8 & 0xff );
            iv[ 15 ] = (byte)( offset       & 0xff );

            if ( ( cipher = mCipher.get() ) == null ) throw new GeneralSecurityException( \"Unable to initialize Cipher( \\\"AES/CTR/NoPadding\\\" )\" );
            cipher.init( Cipher.DECRYPT_MODE,mKey,new IvParameterSpec( iv ) );

            long startTime = System.currentTimeMillis();
            data = cipher.doFinal( data );
            System.out.println( \"decryption of \" + data.length + \" bytes took \" + ( ( System.currentTimeMillis() - startTime ) / 1000.0 ) + \"s\" );

            // cipher.doFinal() takes 5.9s on Samsung Galaxy emulator for 128kb block
            // cipher.doFinal() takes 2.6s on Samsung Galaxy hardware for 128kb block
        } finally {
            if ( input != null ) try { input.close(); } catch ( Exception e ) { }
        }

        // the default order of ByteBuffer is BIG_ENDIAN so it is unnecessary to explicitly set the order()

        return ByteBuffer.wrap( data,prefix,length );
    }
}
    

解决方法

        是的,像这样包含功能中的繁重工作正是NDK发挥作用的地方。请记住,Java是可解释的,而在2.2之前的Android上,没有JIT,因此每条指令每次都会被解释-这是一个巨大的开销。 即使使用JIT,每个数组访问也会执行隐式边界检查,因此存在大量开销。 如果您使用C ++编写此函数,它将明显更快。     

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...