Ap4StreamCipher.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:5k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /*
  2.  * Copyright (c) 2005 Gilles Boccon-Gibod 
  3.  */
  4. /*----------------------------------------------------------------------
  5. |       includes
  6. +---------------------------------------------------------------------*/
  7. #include "Ap4StreamCipher.h"
  8. /*----------------------------------------------------------------------
  9. |       AP4_StreamCipher::AP4_StreamCipher
  10. +---------------------------------------------------------------------*/
  11. AP4_StreamCipher::AP4_StreamCipher(const AP4_UI08* key,
  12.                                    const AP4_UI08* salt,
  13.                                    AP4_Size        iv_size) :
  14.     m_StreamOffset(0),
  15.     m_IvSize(iv_size),
  16.     m_BlockCipher(NULL)
  17. {
  18.     // clamp the IV size to the max supported size
  19.     if (iv_size > 4) {
  20.         m_IvSize = 4;
  21.     }
  22.     // set the initial state
  23.     Reset(key, salt);
  24. }
  25. /*----------------------------------------------------------------------
  26. |       AP4_StreamCipher::~AP4_StreamCipher
  27. +---------------------------------------------------------------------*/
  28. AP4_StreamCipher::~AP4_StreamCipher()
  29. {
  30.     // delete the block cipher
  31.     if (m_BlockCipher) {
  32.         delete m_BlockCipher;
  33.     }
  34. }
  35. /*----------------------------------------------------------------------
  36. |       AP4_StreamCipher::Reset
  37. +---------------------------------------------------------------------*/
  38. AP4_Result
  39. AP4_StreamCipher::Reset(const AP4_UI08* key, const AP4_UI08* salt) 
  40. {
  41.     if (salt) {
  42.         // initialize the counter with a salting key
  43.         for (AP4_UI32 i=0; i<AP4_AES_BLOCK_SIZE; i++) {
  44.             m_CBlock[i] = salt[i];
  45.         }
  46.     } else {
  47.         // initialize the counter with no salting key
  48.         for (AP4_UI32 i = 0; i < AP4_AES_BLOCK_SIZE; i++) {
  49.             m_CBlock[i] = 0;
  50.         }
  51.     }
  52.     // (re)create the block cipher
  53.     if (key != NULL) {
  54.         // delete the block cipher if needed
  55.         if (m_BlockCipher) {
  56.             delete m_BlockCipher;
  57.         }
  58.         
  59.         // (re)create one
  60.         m_BlockCipher = new AP4_AesBlockCipher(key);
  61.     }
  62.     // reset the stream offset
  63.     SetStreamOffset(0);
  64.   
  65.     return AP4_SUCCESS;
  66. }
  67. /*----------------------------------------------------------------------
  68. |       AP4_StreamCipher::SetCounter
  69. +---------------------------------------------------------------------*/
  70. void
  71. AP4_StreamCipher::SetCounter(AP4_Offset block_offset)
  72. {
  73.     // set the counter bytes
  74.     for (AP4_UI32 i = 0; i < m_IvSize; i++) {
  75.         m_CBlock[AP4_AES_BLOCK_SIZE-1-i] = 
  76. (AP4_UI08)((block_offset>>(8*i)) & 0xFF);
  77.     }
  78. }
  79. /*----------------------------------------------------------------------
  80. |       AP4_StreamCipher::SetStreamOffset
  81. +---------------------------------------------------------------------*/
  82. AP4_Result
  83. AP4_StreamCipher::SetStreamOffset(AP4_Offset offset)
  84. {
  85.     // do nothing if we're already at that offset
  86.     if (offset == m_StreamOffset) return AP4_SUCCESS;
  87.     // update the offset
  88.     m_StreamOffset = offset;
  89.     // update the key stream if necessary
  90.     if (m_StreamOffset & 0xF) {
  91.         return UpdateKeyStream(m_StreamOffset/AP4_AES_BLOCK_SIZE);
  92.     }
  93.     
  94.     return AP4_SUCCESS;
  95. }
  96. /*----------------------------------------------------------------------
  97. |       AP4_StreamCipher::UpdateKeyStream
  98. +---------------------------------------------------------------------*/
  99. AP4_Result
  100. AP4_StreamCipher::UpdateKeyStream(AP4_Offset block_offset)
  101. {
  102.     // compute the new counter
  103.     SetCounter(block_offset);
  104.     // compute the key block (x) from the counter block (c)
  105.     return m_BlockCipher->EncryptBlock(m_CBlock, m_XBlock);
  106. }
  107. /*----------------------------------------------------------------------
  108. |       AP4_StreamCipher::ProcessBuffer
  109. +---------------------------------------------------------------------*/
  110. AP4_Result
  111. AP4_StreamCipher::ProcessBuffer(const AP4_UI08* in, 
  112.                                 AP4_UI08*       out, 
  113.                                 AP4_Size        size)
  114. {
  115.     if (m_BlockCipher == NULL) return AP4_ERROR_INVALID_STATE;
  116.     while (size) {
  117.         // compute the number of bytes available in this chunk
  118.         AP4_UI32 index = m_StreamOffset & (AP4_AES_BLOCK_SIZE-1);
  119.         AP4_UI32 chunk;
  120.         // update the key stream if we are on a boundary
  121.         if (index == 0) {
  122.             UpdateKeyStream(m_StreamOffset/AP4_AES_BLOCK_SIZE);
  123.             chunk = AP4_AES_BLOCK_SIZE;
  124.         }
  125.         // compute the number of bytes remaining in the chunk
  126.         chunk = AP4_AES_BLOCK_SIZE - index;
  127.         if (chunk > size) chunk = size;
  128.         // encrypt/decrypt the chunk
  129.         AP4_UI08* x = &m_XBlock[index];
  130.         for (AP4_UI32 i = 0; i < chunk; i++) {
  131.             *out++ = *in++ ^ *x++;
  132.         }
  133.         // update offset and size
  134.         m_StreamOffset += chunk;
  135.         size -= chunk;
  136.     }
  137.     return AP4_SUCCESS;
  138. }