나는 이걸 너무 오래 쓰긴했지만 ...
문제는 블록 크기입니다. TDCP_rijndael은 MCRYPT_RIJNDAEL_128 (_256 아님)과 동일합니다. 그러나 ciph.Init (...) 호출의 '256'값은 여전히 정확합니다. 그것보다 꽤 괜찮아 보인다. 즉, 키/iv에 ansistrings을 사용하고 있거나 유니 코드가 아닌 델파이를 사용하고 있다고 가정합니다.
유니 코드 Delphi 버전에서는 TBytes와 key [0]/iv [0]을 사용하려고합니다.
여백은 여전히 문제 일 수 있습니다. 그렇다면 PHP 매뉴얼 페이지와 시행 착오를 토대로 필자가 맹목적으로 작성한 내용이 여기에있다.
는 PHP :
function Encrypt($src, $key, $iv)
{
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, 'cbc');
//echo "Block size: " . $block . "\r\n";
$pad = $block - (strlen($src) % $block);
$src .= str_repeat(chr($pad), $pad);
$enc = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $src, MCRYPT_MODE_CBC, $iv);
$r = base64_encode($enc);
return $r;
}
function Decrypt($src, $key, $iv)
{
$enc = base64_decode($src);
$dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $enc, MCRYPT_MODE_CBC, $iv);
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, 'cbc');
$pad = ord($dec[($len = strlen($dec)) - 1]);
return substr($dec, 0, strlen($dec) - $pad);
}
델파이 :
function DecryptData(Data: string; AKey: AnsiString; AIv: AnsiString): string;
var
key, iv, src, dest: TBytes;
cipher: TDCP_rijndael;
slen, pad: integer;
begin
//key := Base64DecodeBytes(TEncoding.UTF8.GetBytes(AKey));
//iv := Base64DecodeBytes(TEncoding.UTF8.GetBytes(AIv));
key := TEncoding.ASCII.GetBytes(AKey);
iv := TEncoding.ASCII.GetBytes(AIv);
src := Base64DecodeBytes(TEncoding.UTF8.GetBytes(Data));
cipher := TDCP_rijndael.Create(nil);
try
cipher.CipherMode := cmCBC;
slen := Length(src);
SetLength(dest, slen);
cipher.Init(key[0], 256, @iv[0]); // DCP uses key size in BITS not BYTES
cipher.Decrypt(src[0], dest[0], slen);
// Remove the padding. Get the numerical value of the last byte and remove
// that number of bytes
pad := dest[slen - 1];
SetLength(dest, slen - pad);
// Base64 encode it
result := TEncoding.Default.GetString(dest);
finally
cipher.Free;
end;
end;
function EncryptData(Data: string; AKey: AnsiString; AIv: AnsiString): string;
var
cipher: TDCP_rijndael;
key, iv, src, dest, b64: TBytes;
index, slen, bsize, pad: integer;
begin
//key := Base64DecodeBytes(TEncoding.UTF8.GetBytes(AKey));
//iv := Base64DecodeBytes(TEncoding.UTF8.GetBytes(AIv));
key := TEncoding.ASCII.GetBytes(AKey);
iv := TEncoding.ASCII.GetBytes(AIv);
src := TEncoding.UTF8.GetBytes(Data);
cipher := TDCP_rijndael.Create(nil);
try
cipher.CipherMode := cmCBC;
// Add padding.
// Resize the Value array to make it a multiple of the block length.
// If it's already an exact multiple then add a full block of padding.
slen := Length(src);
bsize := (cipher.BlockSize div 8);
pad := bsize - (slen mod bsize);
Inc(slen, pad);
SetLength(src, slen);
for index := pad downto 1 do
begin
src[slen - index] := pad;
end;
SetLength(dest, slen);
cipher.Init(key[0], 256, @iv[0]); // DCP uses key size in BITS not BYTES
cipher.Encrypt(src[0], dest[0], slen);
b64 := Base64EncodeBytes(dest);
result := TEncoding.Default.GetString(b64);
finally
cipher.Free;
end;
end;
PHP의 델파이 기능은 이제 나에게 같은 대답을 제공합니다.
function Base64DecodeBytes(Input: TBytes): TBytes;
var
ilen, rlen: integer;
begin
ilen := Length(Input);
SetLength(result, (ilen div 4) * 3);
rlen := Base64Decode(@Input[0], @result[0], ilen);
// Adjust the length of the output buffer according to the number of valid
// b64 characters
SetLength(result, rlen);
end;
나는 암호화를 모두 구현 제안 모두 PHP와 델파이의 기능을 해독 할 것이다 :
편집
Base64DecodeBytes 내가 DCP Base64로 장치에 추가 코드의 약간이었다. 그런 다음 둘 다 동일한 중간 값을 생성하고 서로의 중간 값을 해독 할 수 있는지 확인할 수 있습니다.체계적으로 문제가 있는지 또는 특정 기능에 오류가 있는지 여부를 결정해야합니다. – Gus
nist.gov 웹 사이트와 많은 다른 곳에서 이러한 구현이 어떻게 작동하는지 확인할 수있는 수많은 테스트 벡터가 있습니다. 델파이 함수의 '데이터'처리는 나에게 잘못되었습니다. base64 디코딩의 결과는 UTF8로 인코딩 된 문자열이 아닌 임의의 바이트 여야합니다. –
@ GregS, 나는 암호화되지 않은 일반 텍스트를 base64로 해독하려고 시도했지만 정상적으로 처리됩니다. 나는 그 문제가 거기에 있다고 생각하지 않는다. 비록 그렇다하더라도, 나는 다른 최종 결과를 얻은 2 개의 다른 Base64 구현을 시도했다. – Josh