지난 주말에 암호문이 다음과 같은 16진수인 암호화 문제가 발생했습니다.
FC 89 BF C2 B0 5F 1C 2E 64 B8 78 43 92 78 3A C9
나는 이것이 AES/Rijndael 128비트 ECB를 사용하여 암호화되었음을 확실히 알고 있으며 키는 REDRYDER이며 이를 확인하기 위한 솔루션이 이미 게시되었습니다. 일반 텍스트는 FLAG=DAISY입니다. 나는 솔트나 IV 문자열 없이 이를 해독하는 간단한 PHP mcrypt 스크립트를 작성했으며 제대로 해독되었습니다. 그러나 openssl을 사용하려고 하면 일반 텍스트가 표시되지 않습니다.
echo "0: FC 89 BF C2 B0 5F 1C 2E 64 B8 78 43 92 78 3A C9" | xxd -r | openssl aes-128-ecb -d -k REDRYDER -nosalt -nopad ; echo
이것은 단지 일부 이진 데이터를 출력합니다. 또한 바이트 스왑을 수행하기 위해 dd conv=swab을 통해 입력을 전달해 보았습니다.
내가 도대체 뭘 잘못하고있는 겁니까?
답변1
명령 openssl
줄 도구는 OpenSSL 라이브러리의 데모입니다. 꽤 우연한 인터페이스와 열악한 문서를 가지고 있습니다. OpenSSL 라이브러리를 테스트하는 것 이외의 용도로는 사용하지 않는 것이 좋습니다. (예, 로 CA를 관리하는 사람들이 있습니다 openssl
. 그들의 정신이 두렵습니다.)
AES비밀번호가 아닌 키로 작동합니다. AES-128 키는 정확히 16바이트입니다.
옵션은 -k
키를 입력으로 사용하지 않고 비밀번호를 사용합니다. 이 비밀번호는 해시되어 키를 파생합니다. 기본값은 MD5이며 명령줄 옵션으로 재정의할 수 있습니다 -md
. 내가 볼 수 있는 한 이것은 매뉴얼에 문서화되어 있지 않습니다. 단지 소스( apps/enc.c
, 호출 EVP_BytesToKey
)를 읽어야 합니다. MD5 다이제스트는 모든 문자열에서 16바이트 값을 생성하지만 여기서는 이것이 사용되지 않습니다. 이 경우 키는 실제로 null 바이트인 REDRYDER\0\0\0\0\0\0\0\0
위치에 있습니다 \0
.
이 옵션을 -K
사용하면 16진수로 키를 전달할 수 있습니다. 키 크기보다 적은 바이트를 전달하면 OpenSSL은 null 바이트로 완료됩니다. 따라서 키를 전달하려면 다음을 REDRYDER\0\0\0\0\0\0\0\0
전달할 수 있습니다 .$(echo REDRYDER | od -An -tx1 | tr -d ' ')
5245445259444552
키 52454452594445520000000000000000을 사용하여 암호문 블록 FC89BFC2B05F1C2E64B8784392783AC9의 AES-128-ECB 암호 해독 작업은 464c41473d4441495359000000000000을 생성합니다. 바이트 시퀀스를 나타내는 16진수). 그건 FLAG=DAISY\0\0\0\0\0\0
.
이와 같은 작은 암호화 조작을 위해 나는 Python 최상위 수준을 좋아합니다.파이크립토도서관.
>>> from binascii import hexlify, unhexlify
>>> from Crypto.Cipher import AES
>>> ciphertext = unhexlify('FC 89 BF C2 B0 5F 1C 2E 64 B8 78 43 92 78 3A C9'.replace(' ', ''))
>>> key = 'REDRYDER'.ljust(16, '\0')
>>> AES.new(key, AES.MODE_ECB).decrypt(ciphertext)
'FLAG=DAISY\x00\x00\x00\x00\x00\x00'
답변2
이것은 작동합니다:
echo '0: FC89BFC2B05F1C2E64B8784392783AC9' | xxd -r | openssl enc -aes-128-ecb -d -nopad -nosalt -K 5245445259444552
-k 옵션에 대한 입력을 이해하지 못하지만 일반 텍스트 키를 16진수(적절한 바이트 순서)로 변환하고 대신 -K를 사용하면 작동합니다.
openssl은 부두입니다!