2014-07-15 3 views
1

해결할 수없는 까다로운 문제가 있습니다. 서명되지 않은 문자 버퍼와 그 크기 (바이너리이기 때문에)를 받아들이는 dll을 만들고 있습니다. 그럼 내가 암호화하고 버퍼를 반환합니다. 이 함수의 호출 원은 나중에이 버퍼를 파일에 씁니다.데이터가 키 크기의 배수가 아닌 경우 암호화 및 해독

파일 크기가 클수록 호출자는 파일 쓰기 전에 버퍼를 고정 크기가 아닌 암호화 (chunk)로 보내야합니다. 결국 최종 파일이 암호화됩니다.

이제 암호화를 위해 버퍼의 각 문자를 암호화하는 16 자 키를 사용하고 있습니다. 버퍼 크기는 16의 배수가 아니기 때문에 내 키의 모든 문자가 암호화에 사용되지 않을 수도 있습니다. 이로 인해 해독 중에 문제가 발생합니다. 모든 문자가 동일한 키 패턴을 사용하여 암호화되지는 않기 때문입니다. 따라서 암호 해독에 실패합니다.

이 문제를 어떻게 해결할 수 있습니까?

답변

3

block ciphers은 대칭 키가 AES이고 블록 크기의 배수가되어야합니다. 그들은 항상이 문제를 블록 크기의 배수가되도록 padding 데이터로 해결합니다. 이 경우 "블록"의 크기는 단순히 키의 크기입니다.

패딩에 대한 일반적인 접근 방법은 PKCS#7입니다. 여기에서 패딩을 위해 선택한 문자는 패딩 할 바이트 수를 나타냅니다. 예를 들어 블록 크기가 16 바이트이고 데이터 길이가 60 바이트라고 가정 해 보겠습니다. 즉, 3 블록을 완전히 채울 수 있습니다. 마지막 블록에는 12 바이트의 데이터와 4 개의 사용되지 않은 바이트가 있습니다. 따라서 4 개의 사용되지 않은 모든 바이트를 값 4로 채 웁니다. 61 바이트의 데이터가있는 경우 마지막 블록에 사용되지 않은 바이트가 3 개 있으므로 3의 값으로 3 바이트를 채 웁니다.

라이브러리를 암호화 할 때 패딩을 추가하고 해독 할 때 패딩을 제거하도록 API를 설계해야합니다. 사용자는하지 않아도됩니다.

+0

답변 해 주셔서 감사합니다. 내 문제에 대한 완벽한 해결책 인 것 같습니다. 내 패딩 값이 실제 가치와 동일한 상황이 있습니까? 그러한 시나리오에서 우리는 어떻게 구별 할 수 있습니까? – AnswerSeeker

+0

PKCS # 7 패딩은 모호하지 않습니다. 즉 마지막 바이트를보고 데이터 버퍼에서 해당 바이트 수를 빼서 패딩이 무엇인지 항상 알 수 있습니다. 그 의미는 입력 내용이 정확히 블록 크기의 길이 인 경우, PKCS # 7없이 해당 상황에 채워 넣지 않아도 패딩 블록 (모두 값 16)을 추가해야합니다. . 다른 패딩 방식을 사용하는 경우 데이터의 작은 헤더를 암호화하여 길이를 알려줄 수 있습니다. – indiv

+2

이 스키마에 대한 데이터가 침입으로부터 데이터를 보호하지 않는다는 점에 유의하고 싶습니다. 길이 헤더를 추가하면 공격자가 암호화 된 데이터를 단순히 뒤집어 놓는 것을 막을 수있는 방법은 없으며 암호를 해독하면 다른 길이가됩니다. 나는 당신의 암호화 계획이 오직 교육적인 목적을위한 것이라는 가정하에이 질문에 답했습니다. – indiv

2

이 문제를 설명한대로하면 암호의 ECB 모드를 사용하고있는 것입니다. ECB (전자 코드북)는 각 블록을 독립적으로 암호화 함을 의미합니다. 이것은 암호화하기에 매우 불안전 한 방법이므로 많은 경우 암호화로 간신히 자격이 있습니다.

각 16 바이트를 독립적으로 암호화하면 동일한 16 바이트가 일반 텍스트에 나타날 때마다 동일한 16 바이트가 암호문에 나타납니다. 패턴이있는 데이터 (대부분의 데이터에는 패턴이 있음)에서 데이터를 해독하는 데 사용할 수 있습니다.

이 문제를 해결하기 위해 CBC (가장 일반적인 방법)와 같은 다른 블록 암호화 모드를 사용합니다. CBC는 각 블록의 출력을 다음 블록의 암호화로 믹스합니다. CBC를 사용할 때 @indiv가 설명하는대로 PKCS # 7 패딩을 사용하는 것이 일반적입니다. 다른 솔루션도 있지만 PKCS # 7은 일반적으로 구현하기 쉽습니다. 데이터를 사용할 때 주어진 데이터가 16 바이트의 배수이면 16 0x10 바이트의 추가 블록을 추가해야합니다.

0으로 채우면 안됩니다. 이것은 모호합니다 (원본 데이터가 0으로 끝나는 경우 어떻게됩니까?) 확장 공격을 허용합니다. 이것이 PKCS # 7이 존재하는 이유입니다.

자신의 암호를 작성하는 것은 매우 어려운 일이며, 잘못 처리하는 것은 매우 쉽습니다. 이러한 상황을 처리하는 데 필요한 도구가있는 기존 라이브러리를 사용하는 것이 좋습니다. C++에서는 cryptopp 또는 Botan을보아야합니다. Botan을 사용하는 경우 CryptoBox 형식을 사용하는 것이 좋습니다. 더 복잡한 문제를 처리합니다 (그리고 암호화 형식을 만드는 데 복잡한 문제가 많이 있습니다).

+0

더 많은 통찰력을 주셔서 감사합니다. 여기에 제안 된 솔루션을 기반으로 필자는 dll이 버퍼를 처리하고 파일 조작을하지 않기 때문에 사용자가 16의 배수로 데이터를 보내야한다는 것을 알고 있습니다. 그래서, 나는 또한 패딩에 더미 데이터를 추가하도록 사용자에게 알려줄 필요가있다. 나는 그들이 그것으로 괜찮은지 확실하지 않다. Crypto 나 Botan에 관해서는 입력이 여전히 키 크기의 배수가 될 것으로 기대합니까? 나는 더 많은 것을 이해하기 위해 Crypto & Botan을 읽을 것입니다. – AnswerSeeker

+2

CryptoBox 형식은 CBC가 아닌 CTR 모드를 사용하기 때문에 실제로 16 바이트 데이터를 필요로하지 않습니다. 다양한 트레이드 오프가있는 많은 블록 암호 모드가 있습니다. 호출자가 더미 데이터를 추가하지 않아야합니다. 모든 패딩은 내부적으로 처리해야합니다 (PKCS # 7 스키마가 이에 해당됩니다). 다시 말하지만, 암호화 형식을 만드는 것은 매우 까다 롭습니다. 내가 유지하는 RNCryptor 형식을 고려할 수도 있습니다. https://github.com/RNCryptor/RNCryptor-cpp에서 C++ 구현 (유지 관리하지 않음)이 있습니다. –

+0

여기에 AES와 같은 암호화 알고리즘이 있으며 CBC (AES-CBC 제공)와 같은 암호화 모드가 있으며 RNCryptor, CryptoBox, OpenSSL 및 AESCrypt와 같은 암호화 * 형식이 있습니다. 각 레이어는 자체적으로 문제를 제기 할 수 있으므로 최고 수준에서 선택하는 것이 좋습니다 (자체 AES-CBC 암호화기를 만드는 대신 CryptoBox와 같은 고급 형식을 사용하는 것이 좋습니다). –