Cocoa, verilerin şifrelenmesi PHP çözme (ve tersi)

2 Cevap php

Durum ben çözmeye çalışıyorum: Benim kakao app, ben, bir simetrik şifreleme ile bir dize şifrelemek PHP bunu POST, ve bu komut verilerin kodunu olması gerekir. Işlemi (PHP kodlar, Kakao decodes) bir cevap döndürmek için ters çalışmak gerekiyor.

Bir uygulama diğer kodlu verileri gönderdiğinde ben anahtar ve başlatma vektörü (iv) PHP ve kakao hem de aynı olması hem de alabilirsiniz olsa bile, kod çözme çalışır asla çünkü ben bir şey eksik. Hem iş sadece para cezası kodlama / (emin bazı PEBKAC eldeki konu yoktu yapmak doğrulanmadı) kendi veri çözme. Ben bir padding sorunu yerde orada bir şüphe var, ben sadece bunu görmüyorum.

Benim kakao app SSCrypto (OpenSSL fonksiyonlarının etrafında sadece kullanışlı-züppe sarıcı olan) kullanarak kodlar. Şifre Blowfish, modu CBC olduğunu. (Bellek sızıntılarını affet, kod çıplak şartları için elimden olmuştur)

NSData *secretText = [@"secretTextToEncode" dataUsingEncoding:NSUTF8StringEncoding];
NSData *symmetricKey = [@"ThisIsMyKey" dataUsingEncoding:NSUTF8StringEncoding];

unsigned char *input = (unsigned char *)[secretText bytes];
unsigned char *outbuf;
int outlen, templen, inlen;
inlen = [secretText length];

unsigned char evp_key[EVP_MAX_KEY_LENGTH] = {"\0"};
int cipherMaxIVLength = EVP_MAX_IV_LENGTH;
EVP_CIPHER_CTX cCtx;
const EVP_CIPHER *cipher = EVP_bf_cbc();

cipherMaxIVLength = EVP_CIPHER_iv_length( cipher );
unsigned char iv[cipherMaxIVLength];

EVP_BytesToKey(cipher, EVP_md5(), NULL, [symmetricKey bytes], [symmetricKey length], 1, evp_key, iv);

NSData *initVector = [NSData dataWithBytes:iv length:cipherMaxIVLength];

EVP_CIPHER_CTX_init(&cCtx);

if (!EVP_EncryptInit_ex(&cCtx, cipher, NULL, evp_key, iv)) {
	EVP_CIPHER_CTX_cleanup(&cCtx);
	return nil;
}
int ctx_CipherKeyLength = EVP_CIPHER_CTX_key_length( &cCtx );
EVP_CIPHER_CTX_set_key_length(&cCtx, ctx_CipherKeyLength);

outbuf = (unsigned char *)calloc(inlen + EVP_CIPHER_CTX_block_size(&cCtx), sizeof(unsigned char));

if (!EVP_EncryptUpdate(&cCtx, outbuf, &outlen, input, inlen)){
	EVP_CIPHER_CTX_cleanup(&cCtx);
	return nil;
}
if (!EVP_EncryptFinal(&cCtx, outbuf + outlen, &templen)){
	EVP_CIPHER_CTX_cleanup(&cCtx);
	return nil;
}
outlen += templen;
EVP_CIPHER_CTX_cleanup(&cCtx);

NSData *cipherText = [NSData dataWithBytes:outbuf length:outlen];

NSString *base64String = [cipherText encodeBase64WithNewlines:NO];
NSString *iv = [initVector encodeBase64WithNewlines:NO];

base64String ve iv sonra çözmeye çalışır PHP nakledilir:

<?php

import_request_variables( "p", "p_" );

if( $p_data != "" && $p_iv != "" )
{
    $encodedData = base64_decode( $p_data, true );
	$iv = base64_decode( $p_iv, true );

    $td = mcrypt_module_open( MCRYPT_BLOWFISH, '', MCRYPT_MODE_CBC, '' );
	$keySize = mcrypt_enc_get_key_size( $td );
	$key = substr( md5( "ThisIsMyKey" ), 0, $keySize );

    $decodedData = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $encodedData, MCRYPT_MODE_CBC, $iv );
    mcrypt_module_close( $td );

    echo "decoded: " . $decodedData;
}
?>

decodedData hep anlamsız olduğunu.

Ben Kakao PHP kodlanmış çıkışı gönderme süreci tersine denedim ama EVP_DecryptFinal () NULL padding sorunu yerde var inanmak için bana yol ne olduğu, başarısız olur. Ben okumak ve yeniden okuyun PHP ve OpenSSL docs ama şimdi hepsi bir arada bulanıklık ve ben denemek için fikir bitti ettik.

2 Cevap

Ben en önemli problem dize ham şifreleme anahtarı türetmek gibi bir yöntem olup, iki tarafta farklı olduğunu düşünüyorum. EVP_BytesToKey () ham bayt dize döndürmek oldukça karmaşık bir karma rutin ise php md5 () fonksiyonu, size anahtar boyutu aşağı doğrama onaltılık dize, yani 'a476c3 ...' döndürür. Bu olabilir, parametreler ham MD5 hash aşağı basitleştirmek verilen, ama gerçekten söyleyemem ile. Her iki durumda da, bu php karma farklı olacak.

Eğer bir ham md5 hash verecek ("ThisIsMyKey", DOĞRU), md5 php değiştirirseniz. Şeyler kakao tarafında, SSCrypto en + getMD5ForData: yöntemi aynı dize (bir kenara metin kodlama sorunları) için aynısını oluşturmak gerekir.

Edit: php dize ve Kakao verilerin aynı çıktı, onlar bayt seviyesinde hâlâ farklı. (Zaman NSLogged NSData yardımsever içeriğini bir onaltılık kodlanmış dize yazdırır rağmen) php dize kakao veri ham bayt iken (yani sadece 0-9 ve af oluşur) hex-kodlanmış. Hala ham bayt dize almak için php'nin md5 () fonksiyonu ikinci DOĞRU parametresini eklemeniz gerekir.

Ben sorunu anladım. Kısa cevap: kullanılan anahtar Kakao ve PHP altında farklı uzunluklarda oldu. Uzun cevabı ...

Bu 24 sabit bir anahtar uzunluğu kullanır gibi benim özgün soruşturma 56 16 bayt bir değişken anahtar uzunluğu şifredir Blowfish / CBC kullanıyordum. Anahtar suçlu nasılsa olduğunu Boaz fikri kapalı oluyor, ben şifreleme için TripleDES geçiş bayt. Ben bir sorun fark ettim daha sonra: Kakao / EVP_BytesToKey tarafından döndürülen tuşuna () uzunluğunda 24 bayt oldu, ama () benim anahtar karma md5 tarafından döndürülen değeri sadece 16 oldu.

Sorunun çözümü PHP tuşunu aynı şekilde çıkış uzunluğu en az kadar EVP_BytesToKey yapar (cipherKeyLength + cipherIVLength) oluşturmak sahip oldu. Aşağıdaki PHP sadece (herhangi bir tuz yok sayarak veya tekrarlamalar saymak) yok

$cipher = MCRYPT_TRIPLEDES;
$cipherMode = MCRYPT_MODE_CBC;

$keySize   = mcrypt_get_key_size( $cipher, $cipherMode );
$ivSize    = mcrypt_get_iv_size( $cipher, $cipherMode );

$rawKey = "ThisIsMyKey";
$genKeyData = '';
do
{
	$genKeyData = $genKeyData.md5( $genKeyData.$rawKey, true );
} while( strlen( $genKeyData ) < ($keySize + $ivSize) );

$generatedKey = substr( $genKeyData, 0, $keySize );
$generatedIV  = substr( $genKeyData, $keySize, $ivSize );

$output = mcrypt_decrypt( $cipher, $generatedKey, $encodedData, $cipherMode, $generatedIV );

echo "output (hex)" . bin2hex($output);

Büyük olasılıkla bu çıkış ucunda pkcs 5. dolgu orada olacağım unutmayın. Ekleme ve çıkarma için buraya yorum http://us3.php.net/manual/en/ref.mcrypt.php pkcs5_pad ve pkcs5_unpad için kontrol dolgu dedi.

Temelde, anahtarın ham md5 değerini alır ve bu yeterince uzun değilse, yine bu dize md5 sonucu anahtarı ve md5 ekleyin. , Tekrar durulama, yıkayın. EVP_BytesToKey için man sayfası () aslında ne yaptığını açıklar ve gerekirse bir, tuz değerlerini koymak nerede gösterir. Anahtar yenileyici Bu yöntem aynı zamanda doğru başlatma vektörü (iv) yeniler yüzden onu iletmekten gerekli değildir.

Ama ne Blowfish hakkında?

Bu bir anahtar boyutunu tabanına hangi bir bağlamı kabul etmez gibi EVP_BytesToKey() bir şifre için en küçük anahtar mümkün döndürür. Yani varsayılan boyutu Blowfish için 16 bayt olan tüm olsun, olduğunu. mcrypt_get_key_size(), diğer taraftan, mümkün olan en geniş anahtar boyutu verir. Benim özgün kod Yani aşağıdaki satırları:

$keySize = mcrypt_enc_get_key_size( $td );
$key = substr( md5( "ThisIsMyKey" ), 0, $keySize );

$ Keysize 56 ayarlanır çünkü her zaman 32 karakter tuşuna dönecekti için yukarıdaki kodu değiştirme.:

$cipher = MCRYPT_BLOWFISH;
$cipherMode = MCRYPT_MODE_CBC;

$keySize   = 16;

Balon balığı düzgün okumasına olanak verir ama hemen hemen kalıntıları bir değişken uzunlukta anahtar yarar. Değişken anahtar uzunluğu şifrelere gelince Özetle, EVP_BytesToKey() bozuldu. Eğer bir değişken anahtar şifreleme kullanırken farklı bir anahtar / iv oluşturmanız gerekir. 3DES ne ihtiyacım için çalışacak kadar, çünkü ben içine gitmedi.