随机访问InputStream使用AES CTR模式在android [英] Random access InputStream using AES CTR mode in android

查看:625
本文介绍了随机访问InputStream使用AES CTR模式在android的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我找不到用于随机存取的AES CTR加密的任何工作示例。有人可以指导我如何使用计数器在CTR MODE还如何实现跳转到流中的特定位置?

I am unable to find any working example for AES CTR encryption for random access. Can someone guide me how to use the counter in CTR MODE also how to implement jumping to a specific position in the stream?

默认流实现( CipherInputStream )不会跳过流并且破坏纯文本。

The default stream implementation (CipherInputStream) doesn't skip the stream and it corrupts the plain text.

我试图解密存储在sdcard上的加密视频文件Android。嵌入式HTTP文件服务器即时解密。一切正常工作,直到用户在视频中执行搜索:视频立即停止,因为它收到损坏的视频流。

I am trying to decrypt encrypted Video file stored on sdcard in Android. An embedded HTTP file server decrypts it on the fly. Everything is working fine until a user performs a seek within the video: the video stops immediately because it receives corrupt video stream.

我使用以下代码来初始化和加密/解密流(为了简单起见,我硬编码的密钥,它不会在生产中硬编码)

I am using following code to initialize and encrypt/ decrypt stream (for sake of simplicity i hard coded the keys. it will not be hard coded in production)

    ByteBuffer bb = ByteBuffer.allocate(16);
    bb.put("1234567891230000".getBytes());
    byte[] ivString = bb.array();

    // INITIALISATION
    String keyString = "1234567812345678";
    IvParameterSpec iv = new IvParameterSpec(ivString);
    SecretKeySpec keySpec = new SecretKeySpec(keyString.getBytes(), "AES");

    // FOR ENCRYPTION
    Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
    cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(ivString));
    Inputstream encrypted_is = new CipherInputStream(in, cipher);

    // FOR DECRYPTION
    cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(ivString));
            Inputstream decrypted_is = new CipherInputStream(in, cipher);


推荐答案

流用于顺序访问数据。跳过应该只用于向前跳跃短距离,并标记/重置只是为了跳回小距离。

You should not implement this using a stream. A stream is used for sequential access to data. Skipping should only be used for jumping short distances forward and mark/reset only for jumping small distances back.

使用文件地图可能是最高效。对于稍微简单一些但效率较低的方法,您可以使用 RandomAccessFile 。此外,您应该使用设置为您在文件中开始位置处的计数器的IV,使用 Cipher.getInstance(AES / CTR / NoPadding)

Using a file map is probably the most efficient. For a slightly easier approach but less efficient approach you could use RandomAccessFile instead. You should furthermore use Cipher.getInstance("AES/CTR/NoPadding") using an "IV" that is set to the counter you expect at the location you start within the file.

使用具有偏移量的CTR的示例代码:

Sample code for using CTR with offset:

private static final int AES_BLOCK_SIZE = 16;

public static final void jumpToOffset(final Cipher c,
        final SecretKey aesKey, final IvParameterSpec iv, final long offset) {
    if (!c.getAlgorithm().toUpperCase().startsWith("AES/CTR")) {
        throw new IllegalArgumentException(
                "Invalid algorithm, only AES/CTR mode supported");
    }

    if (offset < 0) {
        throw new IllegalArgumentException("Invalid offset");
    }

    final int skip = (int) (offset % AES_BLOCK_SIZE);
    final IvParameterSpec calculatedIVForOffset = calculateIVForOffset(iv,
            offset - skip);
    try {
        c.init(Cipher.ENCRYPT_MODE, aesKey, calculatedIVForOffset);
        final byte[] skipBuffer = new byte[skip];
        c.update(skipBuffer, 0, skip, skipBuffer);
        Arrays.fill(skipBuffer, (byte) 0);
    } catch (ShortBufferException | InvalidKeyException
            | InvalidAlgorithmParameterException e) {
        throw new IllegalStateException(e);
    }
}

private static IvParameterSpec calculateIVForOffset(final IvParameterSpec iv,
        final long blockOffset) {
    final BigInteger ivBI = new BigInteger(1, iv.getIV());
    final BigInteger ivForOffsetBI = ivBI.add(BigInteger.valueOf(blockOffset
            / AES_BLOCK_SIZE));

    final byte[] ivForOffsetBA = ivForOffsetBI.toByteArray();
    final IvParameterSpec ivForOffset;
    if (ivForOffsetBA.length >= AES_BLOCK_SIZE) {
        ivForOffset = new IvParameterSpec(ivForOffsetBA, ivForOffsetBA.length - AES_BLOCK_SIZE,
                AES_BLOCK_SIZE);
    } else {
        final byte[] ivForOffsetBASized = new byte[AES_BLOCK_SIZE];
        System.arraycopy(ivForOffsetBA, 0, ivForOffsetBASized, AES_BLOCK_SIZE
                - ivForOffsetBA.length, ivForOffsetBA.length);
        ivForOffset = new IvParameterSpec(ivForOffsetBASized);
    }

    return ivForOffset;
}

这篇关于随机访问InputStream使用AES CTR模式在android的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆