Triple DES interoperability between .Net and iPhone?
I need to encrypt a string on the iPhone and send it to a .Net for decryption using Triple DES. I am able to encrypt/decrypt on the iPhone and with .Net, but I get different results in both platforms.
I use the very same code as the encryption/decryption with AES between .Net and iPhone in here
The only thing that I changed .net is the encryption algorithm, so where it says AesCryptoServiceProvider, I put TripleDesServiceProvider
As in .net the only thing that I changed is the encryption algorithm, so where it says kCCAlgorithmAES128, I put kCCAlgorithm3DES
What am I missing?
[UPDATE]
Thanks for your responses.
If I stay in the same platform I can encrypt/decrypt without a problem, but if I encrypt in iPhone and decrypt in .net there is a problem because in each platform has different results with the same inputs.
As Overslacked said I think the problem has to do with salt, but I couldn't find any sha or md5 documentation that the algorithm is using in each platform, or any parameter to customize this.
Here is the code that I am actually using in iPhone:
int main(int argc, char *argv[]){
NSString * _secret = @"hello";
NSString * _key = @"1234567890";
_out = [self doCipher:_secret key:_key context:kCCEncrypt];
NSLog(@"encrypted data in str: %@", _out);
_outDecrypted = [StringEncryption doCipher:_out key:_key context:kCCDecrypt];
NSLog(@"decrypted data in str: %@", _outDecrypted);
}
+ (NSString *)doCipher:(NSString *)sTextIn key:(NSString *)sKey
context:(CCOperation)encryptOrDecrypt {
NSMutableData * dTextIn;
if (encryptOrDecrypt == kCCDecrypt) {
dTextIn = [[[NSData alloc] base64DecodeString:sTextIn ]mutableCopy];
}
else{
dTextIn = [[sTextIn dataUsingEncoding: NSASCIIStringEncoding]mutableCopy];
}
NSMutableData * dKey = [[sKey dataUsingEncoding:NSASCIIStringEncoding]mutableCopy];
[dKey setLength:24];
uint8_t *bufferPtr1 = NULL;
size_t bufferPtrSize1 = 0;
size_t movedBytes1 = 0;
uint8_t iv[kCCBlockSize3DES];
memset((void *) iv, 0x0, (size_t) sizeof(iv));
bufferPtrSize1 = ([sTextIn length] + kCCBlockSize3DES) & ~(kCCBlockSize3DES -1);
bufferPtr1 = malloc(bufferPtrSize1 * sizeof(uint8_t));
memset((void *)bufferPtr1, 0x00, bufferPtrSize1);
ccStatus = CCCrypt(encryptOrDecrypt, // CCOperation op
kCCAlgorithm3DES, // CCAlgorithm alg
kCCOptionPKCS7Padding, // CCOptions options
[dKey bytes], // const void *key
[dKey length], // size_t keyLength
iv, // const void *iv
[dTextIn bytes], // const void *dataIn
[dTextIn length], // size_t dataInLength
(void *)bufferPtr1, // void *dataOut
bufferPtrSize1, // size_t dataOutAvailable
&movedBytes1); // size_t *dataOutMoved
NSString * sResult;
if (encryptOrDecrypt == kCCDecrypt){
sResult = [[[ NSString alloc] initWithData:[NSData dataWithBytes:bufferPtr1
length:movedBytes1] encoding:NSASCIIStringEncoding] autorelease];
}
else {
NSData *dResult = [NSData dataWithBytes:bufferPtr1 length:movedBytes1];
sResult = [dResult base64EncodeData:dResult];
}
return sResult;
}
Here is the code that I am using for .net
class Program
{
static void Main(string[] args)
{
string key = "1234567890";
string secret = "hello";
string crypto = EncryptedString.EncryptString(secret, key);
Console.WriteLine(crypto);
secret = EncryptedString.DecryptString(crypto, key);
Console.WriteLine(secret);
Main(null);
}
}
public class EncryptedString
{
public static string EncryptString(string plainSourceStringToEncrypt, s开发者_如何转开发tring passPhrase)
{
//Set up the encryption objects
using (TripleDESCryptoServiceProvider acsp = GetProvider(Encoding.ASCII.GetBytes(passPhrase)))
{
byte[] sourceBytes = Encoding.ASCII.GetBytes(plainSourceStringToEncrypt);
ICryptoTransform ictE = acsp.CreateEncryptor();
//Set up stream to contain the encryption
MemoryStream msS = new MemoryStream();
//Perform the encrpytion, storing output into the stream
CryptoStream csS = new CryptoStream(msS, ictE, CryptoStreamMode.Write);
csS.Write(sourceBytes, 0, sourceBytes.Length);
csS.FlushFinalBlock();
//sourceBytes are now encrypted as an array of secure bytes
byte[] encryptedBytes = msS.ToArray(); //.ToArray() is important, don't mess with the buffer
String b64 = System.Text.ASCIIEncoding.ASCII.GetString(encryptedBytes);
return Convert.ToBase64String(encryptedBytes);
}
}
public static string DecryptString(string base64StringToDecrypt, string passphrase)
{
//Set up the encryption objects
using (TripleDESCryptoServiceProvider acsp = GetProvider(Encoding.Default.GetBytes(passphrase)))
{
byte[] RawBytes = Convert.FromBase64String(base64StringToDecrypt);
ICryptoTransform ictD = acsp.CreateDecryptor();
MemoryStream msD = new MemoryStream(RawBytes, 0, RawBytes.Length);
CryptoStream csD = new CryptoStream(msD, ictD, CryptoStreamMode.Read);
return (new StreamReader(csD)).ReadToEnd();
}
}
private static TripleDESCryptoServiceProvider GetProvider(byte[] key)
{
TripleDESCryptoServiceProvider result = new TripleDESCryptoServiceProvider();
result.Mode = CipherMode.CBC;
result.Padding = PaddingMode.PKCS7;
result.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
result.Key = key;
return result;
}
}
AES keys are 128, 192 or 256 bits, 192 is rarely seen.
Triple DSE is usually 112 bits but can be 168 bits. Notice that this is specified in bits. Triple DES expects each byte to have a parity bit and thus 7 data bits. Usually Triple DES is used in a compatibility mode (compatible with Single DES) by performing single DES encode, decode and encode with one key used for both an encode and decode, k1, k2, k1. Thus 8 byte key * 7 bits * 2 = 112. Sometimes decode, encode, decode is used so this too can be a problem.
Get the keys correct first. Since you are changing from AES to 3DES the key sizes will be different, that may be a problem. Also make sure the modes and IVs are correct.
The best bet is to dump the key, IV (if there is one) and data in hex on both sides of the crypto function and on both platforms. First work to get these to match. Then the problem is in the base64 or whatever other manipulations are involved.
You need to match all of your inputs, keys, salts and algorithms on both sides EXACTLY for this to work. AesCryptoServiceProvider and TripleDesServiceProvider will produce different results and kCCAlgorithmAES128 and kCCAlgorithm3DES will produce different results.
Be mindful of the random value that .Net's crypto package will add to your data before encryption, if I recall correctly it's usually the first 16 bits of data.
精彩评论