Hard coded AES-256 key with WinCrypt & CryptImportKey - cryptography

I need to have a Win32 application load a hard coded AES-256 key, ideally using the WinCrypt.h methods. I've got my key in an unsigned char[32] but I can't find the correct format of a key blob to pass to CryptImportKey. Everything seems to give me invalid parameter errors. Is there any way to do this?
(Also important is how to set IV in WinCrypt. I can't see how to do that at all)

Solved it. I was using the wrong bType and using 256 for keySize instead of 32.
BYTE myPrivateKey[] =
{1,2,3,4,5,6,7,8,9,10,
11,12,13,14,15,16,17,18,19,20,
21,22,23,24,25,26,27,28,29,30,
31,32};
BYTE myIV[] =
{1,2,3,4,5,6,7,8,9,10,
11,12,13,14,15,16};
struct aes256keyBlob
{
BLOBHEADER hdr;
DWORD keySize;
BYTE bytes[32];
} blob;
blob.hdr.bType = PLAINTEXTKEYBLOB;
blob.hdr.bVersion = CUR_BLOB_VERSION;
blob.hdr.reserved = 0;
blob.hdr.aiKeyAlg = CALG_AES_256;
blob.keySize = 32;
memcpy(blob.bytes, myPrivateKey, 32);
HCRYPTKEY hKey;
if (CryptImportKey(hCryptProv, (BYTE*)&blob, sizeof(aes256keyBlob), NULL, 0, &hKey))
{
if(CryptSetKeyParam(hKey, KP_IV, myIV, 0))
{
//do decryption here
}
else{/*error*/}
CryptDestroyKey(hKey);
}
else{/*error*/}

Related

Sample implementation of java CBCBlockCipherMac in Objective c

Can anyone share a sample code on how to implement CBCBlockCipherMac in objective C. here is how far I got and its giving a different result from the java implementation.
const unsigned char key[16] = "\x1\x2\x3\x4\x5\x6\x7\x8\x9\x0\x1\x2\x3\x4\x5\x6";
const unsigned char data[14] = "\x54\x68\x69\x73\x69\x73\x6d\x79\x73\x74\x72\x69\x6e\x67";
CMAC_CTX *ctx = CMAC_CTX_new();
ret = CMAC_Init(ctx, key, sizeof(key), EVP_des_ede3(), 0);
printf("CMAC_Init = %d\n", ret);
ret = CMAC_Update(ctx, data, sizeof(data));
printf("CMAC_Update = %d\n", ret);
size_t size;
//unsigned int size;
unsigned char tag[4];
ret = CMAC_Final(ctx, tag, &size);
printf("CMAC_Final = %d, size = %u\n", ret, size);
CMAC_CTX_free(ctx);
printf("expected: 391d1520\n"
"got: ");
size_t index;
for (index = 0; index < sizeof(tag) - 1; ++index) {
printf("%02x", tag[index]);
if ((index + 1) % 4 == 0) {
printf(" ");
}
}
printf("%02x\n", tag[sizeof(tag) - 1]);
And my java code looks like this
String *data = "Thisismystring";
String *keyString = "1234567890123456";
bytes[]mac = new byte[4];
CBCBlockCipherMac macCipher = new CBCBlockCipherMac(DESedeEngine);
DESedeParameters keyParameter = new DESedeParameters(keyString.getBytes());
DESedeEngine engine = new DESedeEngine();
engine,init(true, keyParameter);
byte[] dataBytes = data.getBytes();
macCipher.update(dataBytes,0,data.length());
macCipher.doFinal(mac,0);
byte[] macBytesEncoded = Hex.encode(mac);
String macString = new String(macBytesEncoded);
This gives me "391d1520". But the objective c gives me "01000000"
CMAC is not the same as CBC MAC. CMAC has an an additional step at the beginning and the end of the calculation. If possible I would suggest you upgrade your Java code to use CMAC, as CBC is not as secure, e.g. using org.bouncycastle.crypto.macs.CMac.
OpenSSL does not seem to implement CBC MAC directly (at least, I cannot find any reference to it). So if you need it, you need to implement it yourself.
You can use CBC mode encryption with a zero IV and take the last 16 bytes of the encryption. Of course, this means you need to store the rest of the ciphertext in a buffer somewhere, or you need to use the update functions smartly (reusing the same buffer over and over again for the ciphertext).

How do I encrypt a string with an RSA public key from a ASN.1 x509 Byte array?

I have an ASN.1 x509 byte array that contains the modulo and the public key of an RSA pair. My goal is to do whatever it takes to use this to encrypt a string. I'm trying to use openssl in objective-c to accomplish this. Whenever I try to get an RSA object using d2i_X509, it returns null. I'm willing to switch to a different library if I can't accomplish this using openssl. Please help me find something that works.
You generally would not encrypt a string using the public key of an X.509 directly. Instead you would generate a strong random(of a specific quality) key; use normal symmetric encryption (such as AES) and then encyrpt the string with that. You then encrypt the random key with the X.509.
Consult a good PKI/Crypto book (e.g. http://www.amazon.com/Applied-Cryptography-Protocols-Algorithms-Source/dp/0471117099) as to why (sections on key leakage, bit-flipping, padding and (re)encrypting twice).
If you really insist on doing this -have a look at https://github.com/dirkx/smime-add-encryption-for-recipient/blob/master/smime-add-encrypt/main.c its pkcs7_encode_rinfo function.
x509cert = ... something to read your x509 byte array in.
unsigned char *stuff = "Some zecret string";
int stufflen = strlen(stuff);
EVP_PKEY *pkey;
EVP_PKEY_CTX *pctx = NULL;
assert(pkey = = X509_get_pubkey( x509cert));
assert(pctx = EVP_PKEY_CTX_new(pkey, NULL));
assert(EVP_PKEY_encrypt_init(pctx)==1);
assert((EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT
EVP_PKEY_CTRL_PKCS7_ENCRYPT, 0, ri)==1);
size_t eklen;
assert(EVP_PKEY_encrypt(pctx, NULL, &eklen, stuff, stufflen)==1);
ek = OPENSSL_malloc(eklen);
assert(ek);
unsigned char *ek = NULL;
assert((EVP_PKEY_encrypt(pctx, ek, &eklen, key, keylen)==1);
printf("Encrypted blurp: ");
for(int i = 0; i < eklen; i++) {
printf("0x%02X ", ek[i];
};
printf("\n");
exit(0);

RSA encryption/decryption in objective c

I am tring to implement RSA encryption in my app using SecKeyEncrypt and SecKeyDecrypt.
The issue is that only when the ciphertext is long as KeyblockSize (128,256 etc), I get it decrypted correctly. Also, for each build and run, I get different results (encrypted data and cipher text length) keeping input plain text the same. And on clean and build several times, once in a while cipher text length becomes keyblocksize and so decrypts properly.
Pls help to understand where the problem is. Thanks in advance
Note: From SecKeyEncrypt's definition got to know that the last parameter gives back the no. of bytes written, i.e. ciphertextlength in bytes. This parameter always returns back my keyblocksize for any input string.
But many times the actual ciphertext length varies with this parameter. And whenever ciphertextlength is same as the parameter, gets decrypted correctly.
Posting encrypt and decrypt portions of my code :
- (void)encryptWithPublicKey:(uint8_t *)plainBuffer cipherBuffer:(uint8_t *)cipherBuffer
{
OSStatus status = noErr;
NSLog(#"** original plain text 0: %s", plainBuffer);
size_t plainBufferSize = strlen((char *)plainBuffer);//
size_t cipherBufferSize = CIPHER_BUFFER_SIZE;// its 1024
SecKeyRef key=[self getPublicKeyRef];
NSLog(#"SecKeyGetBlockSize() public = %lu", SecKeyGetBlockSize(key));//it returns 256
// Error handling
// Encrypt using the public.
status = SecKeyEncrypt([self getPublicKeyRef],
kSecPaddingNone,
plainBuffer,
plainBufferSize,
&cipherBuffer[0],
&cipherBufferSize
);
NSLog(#"encryption result code: %ld (size: %lu)", status, cipherBufferSize);
NSLog(#"encrypted text: %s", cipherBuffer);
}
- (void)decryptWithPrivateKey:(uint8_t *)cipherBuffer plainBuffer:(uint8_t *)plainBuffer
{
OSStatus status = noErr;
size_t cipherBufferSize = strlen((char *)cipherBuffer);
// DECRYPTION
size_t plainBufferSize = BUFFER_SIZE;//its 256
// Error handling
status = SecKeyDecrypt([self getPrivateKeyRef],
kSecPaddingNone,
&cipherBuffer[0],
cipherBufferSize,
&plainBuffer[0],
&plainBufferSize
);
NSLog(#"decryption result code: %ld (size: %lu)", status, plainBufferSize);
NSLog(#"FINAL decrypted text: %s", plainBuffer);
}

my vb.net encryption result does not match the xcode encryption result given the same input parameters

I have set up a method in vb.net and in xcode for encrypting a string using as far as i can tell the same parameters for an AES encryption.
I've looked all over the place but cannot find information on whether they use the same encryption algorithm and settings.
this is the vb.net code:
Dim encryptAES As New AesCryptoServiceProvider()
Dim encoding As New UTF8Encoding()
Dim encryptor As ICryptoTransform
encryptAES.Key = encoding.GetBytes("12345678901234567890123456789032")
encryptAES.IV = encoding.GetBytes("1234567890123416")
encryptAES.Mode = CipherMode.CBC
encryptAES.Padding = PaddingMode.PKCS7
encryptor = encryptAES.CreateEncryptor
Dim input As Byte() = encoding.GetBytes("hello")
Dim result = encryptor.TransformFinalBlock(input, 0, input.Length)
Dim hex As String = ""
For i As Integer = 0 To result.Length - 1
hex = hex & result(i).ToString("X2")
Next
ConsoleWrite(hex)
which matches the output of this php encryption:
<?php
$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
$key256 = '12345678901234567890123456789032';
$iv = '1234567890123416';
$cleartext = 'hello';
printf("plainText: %s\n\n",$cleartext);
if (mcrypt_generic_init($cipher, $key256, $iv) != -1)
{
$cipherText = mcrypt_generic($cipher,$cleartext );
mcrypt_generic_deinit($cipher);
printf("256-bit encrypted result:\n%s\n\n",bin2hex($cipherText));
}
?>
And here's the mac code:
IV = [#"1234567890123416" dataUsingEncoding:NSUTF8StringEncoding];
NSLog([IV base64EncodingWithLineLength:0]);
NSData * localKey = [#"12345678901234567890123456789032" dataUsingEncoding:NSUTF8StringEncoding];
NSLog([localKey base64EncodingWithLineLength:0]);
NSLog(#"encode plaintext:");
NSLog([self.data base64EncodingWithLineLength:0]);
CCCryptorStatus result = CCCrypt( kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
localKey, kCCKeySizeAES256,
IV, //initialization vector
[self.data mutableBytes], [self.data length], //input
buffer, bufferSize, //output
&numBytesEncrypted );
self.data = [self.data initWithBytes:buffer length:numBytesEncrypted];
NSLog(#"encode end result:");
NSLog([self.data base64EncodingWithLineLength:0]);
So as far as I can tell the mac code must be incorrect as it returns a different value (the same length).
Here are the debug dumps from both the pac and mac versions.
pc (values in base64):
key: MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMzI=
iv: MTIzNDU2Nzg5MDEyMzQxNg==
plaintext: aGVsbG8=
encrypted: oiUIdi9StezV93+nXctCKw==
mac (values in base 64):
key: MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMzI=
iv: MTIzNDU2Nzg5MDEyMzQxNg==
plaintext: aGVsbG8=
encrypted: rU5MgfNIjx7zqD5Cdh2mlA==
I also had a look at endianness here is the pc encryped base64 with both endianness and neither match the mac version:
oiUIdi9StezV93+nXctCKw==
K0LLXad/99XstVIvdgglog==
I've now run a test where I've set the key to be 32 0's and the IV to be 16 0's (so endianness should hopefully not matter) and with two more tests heres the results from mac:
BfG2gjzkooiJCXgIQJKyZg== (iOS 5 on device)
n9KJXqThiuKyrNPjo7V7PA== (iOS 5 in simulator)
cCH116bIlLeUOxNDwFt2rg== (iOS 4.3 in simulator)
WTH? all parameters are identical, only change is which version to compile for and each encryption is different...
and the pc result:
wjXeJNI54DzI43fGBPymew==
When inputting the mac encrypted text into the pc to decrypt, I get a 'Padding is invalid and cannot be removed.' error.
Any information anyone could provide would be much appreciated.
Both the mac and pc versions involve first creating a byte array from the sample text, and it is this byte array that is then passed to the encryption algorithm. I would start by comparing those byte arrays to make sure you are encrypting the same data. It looks like in both cases you have utf8 and AES128, but it never hurts to be sure.
Next, the result of the encryption algorithm is also a byte array, which must then be re-encoded as a string. Looking at your results, I see not just two different values, but two completely different kinds of characters. That tells me that the re-encoding may be off. Again, you want to compare the byte arrays.
In both cases, to ensure an accurate compare, I would base64 encode the arrays.

How can I import an RSA public key from either XML or modulus/exponent in native code for use with Windows CAPI's CryptVerifySignature?

In C#, I am able to validate a hash against a public key in either of the following ways:
// Import from raw modulus and exponent
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) {
RSAParameters rsaKeyInfo = new RSAParameters {Modulus = modulus, Exponent = exponent};
rsa.ImportParameters(rsaKeyInfo);
return rsa.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA512"), signature);
}
// Import from XML
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) {
rsa.FromXmlString(xmlPublicKey);
return rsa.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA512"), signature);
}
What I need to know is how I can use CAPI to accomplish the same thing, given an inbound RSA public key?
I have most of the CAPI functions necessary to validate a hash, except for understanding how to import a public key into the cryptographic provider's context:
HCRYPTPROV hCryptProv;
HCRYPTHASH hHash;
CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0);
CryptCreateHash(hCryptProv, CALG_SHA512, 0, 0, &hHash);
CryptHashData(hHash, pDataToHash, lenDataToHash, 0);
CryptVerifySignature(hHash, pSignature, sigLength, NULL, CRYPT_NOHASHOID);
CryptDestroyHash(hHash);
CryptReleaseContext(hCryptProv, 0);
Thanks!
Use CryptImportKey with a PUBLICKEYBLOB:
HCRYPTKEY hPublicKey;
DWORD keyBlobLength = sizeof(BLOBHEADER)+sizeof(RSAPUBKEY)+modulusLengthInBytes;
BYTE* keyBlob = malloc(keyBlobLength);
BLOBHEADER* blobheader = (BLOBHEADER*) keyBlob;
blobheader.bType = PUBLICKEYBLOB;
blobheader.bVersion = CUR_BLOB_VERSION;
blobheader.reserved = 0;
blobheader.aiKeyAlg = CALG_RSA_KEYX;
RSAPUBKEY* rsapubkey = (RSAPUBKEY*) (keyBlob + sizeof(BLOBHEADER));
rsapubkey.magic = 0x31415352;
rsapubkey.bitlen = modulusLengthInBytes*8;
rsapubkey.pubexp = 65537; // Or whatever your public exponent is.
BYTE* modulus = keyBlob + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY);
memcpy(modulus, ..., modulusLengthInBytes); // NOTE: modulus must be in LSB form,
// which is the opposite of what you
// usually have.
// .NET will give you the modulus in
// MSB form, so you will have to
// reverse the order of the bytes.
CryptImportKey(hCryptProv, keyBlob, keyBlobLength, 0, 0, &hPublicKey);