Implementing HMAC encryption algorithm in iPhone application - iphone

I want to implement HMAC encryption algorithm for my iPhone application. Any sample code will really help. Also, please guide me with brief implementation of the same.

Use the Common Crypto functions. The documentation is in man pages, so you'll need to hunt for it a bit. They're in libSystem on iOS and Mac OS X, so no need to add another library or framework to your project. As you can see from the example below, the API is very similar to OpenSSL's.
If you are actually interested in encrypting, as opposed to authenticating data, Common Crypto has functions to perform AES and 3DES (and DES, but don't use it, it's far too weak for modern needs). Take a look at the CCCryptor man page for details.
The example below is equivalent to running openssl dgst -md5 -hmac secret < myfile.txt. Start by initializing the the CCHmacContext, and then call CCHmacUpdate as long as you have data to authenticate. When you've read all the bytes, call CCHmacFinal to get the HMAC into a buffer. I've provided a crude method to convert the HMAC bytes into printable hex.
#include <CommonCrypto/CommonHMAC.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
extern int errno;
int
main( int ac, char *av[] )
{
CCHmacContext ctx;
char *key = "secret";
char buf[ 8192 ];
unsigned char mac[ CC_MD5_DIGEST_LENGTH ];
char hexmac[ 2 * CC_MD5_DIGEST_LENGTH + 1 ];
char *p;
int fd;
int rr, i;
if ( ac != 2 ) {
fprintf( stderr, "usage: %s path\n", av[ 0 ] );
exit( 1 );
}
if (( fd = open( av[ 1 ], O_RDONLY )) < 0 ) {
fprintf( stderr, "open %s: %s\n", av[ 1 ], strerror( errno ));
exit( 2 );
}
CCHmacInit( &ctx, kCCHmacAlgMD5, key, strlen( key ));
while (( rr = read( fd, buf, sizeof( buf ))) > 0 ) {
CCHmacUpdate( &ctx, buf, rr );
}
if ( rr < 0 ) {
perror( "read" );
exit( 2 );
}
CCHmacFinal( &ctx, mac );
(void)close( fd );
p = hexmac;
for ( i = 0; i < CC_MD5_DIGEST_LENGTH; i++ ) {
snprintf( p, 3, "%02x", mac[ i ] );
p += 2;
}
printf( "%s\n", hexmac );
return( 0 );
}

HMAC is not an encryption mechanism, but an authentication digest. It uses an underlying message digest function such as SHA-1, SHA-256, MD5 etc, with a secret key to generate a code that can be used to authenticate data.
Generating an HMAC digest is extremely simple. Here is the description from RFC2104 (via Wikipedia)
Let:
H(·) be a cryptographic hash function (ie. SHA-1, SHA-256, MD5 etc)
K be a secret key padded to the right with extra zeros to the input block size of the hash function, or the hash of the original key if it's longer than that block size
m be the message to be authenticated
| denote concatenation
⊕ denote exclusive or (XOR)
opad be the outer padding (0x5c5c5c…5c5c, one-block-long hexadecimal constant)
ipad be the inner padding (0x363636…3636, one-block-long hexadecimal constant)
Then HMAC(K,m) is mathematically defined by:
HMAC(K,m) = H((K ⊕ opad) | H((K ⊕ ipad) | m)).
For the underlying digest function you can help yourself to one of the C implementations from OpenSSL. In fact it also has a C implementation of HMAC that you can probably just use as is.

Related

Is there a limit above max_dgram_qlen and wmem_{max,default}?

I am trying to determinate the different limits of the unix datagram sockets, as I am using it as IPC for my project.
The obscure thing I want to control is the size of my socket's internal buffer :
I want to know how many datagrams I can send before my socket would block.
I've understood that 2 differents limits affect the size of the socket's buffer :
/proc/sys/net/core/wmem_{max, default} sets the max (-default) size of a socket's writing buffer
/proc/sys/net/unix/max_dgram_qlen sets the maximum number of datagram the buffer can hold
I know that /proc/sys/net/core/rmem_{max, default} sets the max (-default) size of a socket's reading buffer but as I am working on local unix socket it doesn't seem to have a impact.
I have set wmem_{max, default} to 136314880 (130 MB) and max_dgram_qlen to 500000.
And wrote a small program where the sender socket only sends fixed size datagram to the receiver socket until is would block, I then print the size and number of datagram I was able to send.
Here is the code I used :
#include <err.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
/* Payload size in bytes. */
#define PAYLOAD_SIZE 100
#define CALL_AND_CHECK(syscall) \
if (syscall < 0) { err(1, NULL); }
int main(void)
{
int receiver_socket_fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0);
if (receiver_socket_fd < 0)
err(1, NULL);
char* binding_path = "test_socket";
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, binding_path, sizeof(addr.sun_path));
/* Check if the file exists, if yes delete it ! */
if (access(binding_path, F_OK) != -1) {
CALL_AND_CHECK(unlink(binding_path));
}
CALL_AND_CHECK(bind(receiver_socket_fd, (struct sockaddr const*) &addr, sizeof(addr)));
int sender_socket_fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0);
if (sender_socket_fd < 0)
err(1, NULL);
CALL_AND_CHECK(connect(sender_socket_fd, (struct sockaddr const*) &addr, sizeof(addr)));
struct payload { char data[PAYLOAD_SIZE]; };
/* Create test payload with null bytes. */
struct payload test_payload;
memset(&test_payload.data, 0, PAYLOAD_SIZE);
ssize_t total_size_written = 0;
ssize_t size_written = 0;
do {
size_written = write(sender_socket_fd, (const void *) &test_payload, PAYLOAD_SIZE);
if (size_written > 0)
total_size_written += size_written;
} while (size_written > 0);
printf("socket_test: %zu bytes (%ld datagrams) were written before blocking, last error was :\n", total_size_written, total_size_written / PAYLOAD_SIZE);
perror(NULL);
CALL_AND_CHECK(unlink(binding_path));
CALL_AND_CHECK(close(sender_socket_fd));
CALL_AND_CHECK(close(receiver_socket_fd));
return 0;
}
I was expecting to reach either the max size in bytes of the socket (here 130MB) or the max number of datagram I set (500 000).
But the actual result is that I am only able to write 177494 datagrams before being blocked.
I can change the size of my payload it's always the same result (as long as I don't reach the maximum size in bytes first). So it seems that I am hitting a limit above max_dgram_qlen and wmem_{max, default} that I can't found.
I have of course tried to investigate ulimit or limits.conf without success. ulimit -b doesn't even work on my machine (says "options not found" and returns).
I am working on Debian 10 (buster) but have launched my test program on different OS with the same result : I hit a limit of datagram that I don't know about.
Do you have any idea of which limit I didn't see and I am reaching ? And if I can read or modify this limit ?

STM32 SPI data is sent the reverse way

I've been experimenting with writing to an external EEPROM using SPI and I've had mixed success. The data does get shifted out but in an opposite manner. The EEPROM requires a start bit and then an opcode which is essentially a 2-bit code for read, write and erase. Essentially the start bit and the opcode are combined into one byte. I'm creating a 32-bit unsigned int and then bit-shifting the values into it. When I transmit these I see that the actual data is being seen first and then the SB+opcode and then the memory address. How do I reverse this to see the opcode first then the memory address and then the actual data. As seen in the image below, the data is BCDE, SB+opcode is 07 and the memory address is 3F. The correct sequence should be 07, 3F and then BCDE (I think!).
Here is the code:
uint8_t mem_addr = 0x3F;
uint16_t data = 0xBCDE;
uint32_t write_package = (ERASE << 24 | mem_addr << 16 | data);
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_SPI_Transmit(&hspi1, &write_package, 2, HAL_MAX_DELAY);
HAL_Delay(10);
}
/* USER CODE END 3 */
It looks like as your SPI interface is set up to process 16 bit halfwords at a time. Therefore it would make sense to break up the data to be sent into 16 bit halfwords too. That would take care of the ordering.
uint8_t mem_addr = 0x3F;
uint16_t data = 0xBCDE;
uint16_t write_package[2] = {
(ERASE << 8) | mem_addr,
data
};
HAL_SPI_Transmit(&hspi1, (uint8_t *)write_package, 2, HAL_MAX_DELAY);
EDIT
Added an explicit cast. As noted in the comments, without the explicit cast it wouldn't compile as C++ code, and cause some warnings as C code.
You're packing your information into a 32 bit integer, on line 3 of your code you have the decision about which bits of data are placed where in the word. To change the order you can replace the line with:
uint32_t write_package = ((data << 16) | (mem_addr << 8) | (ERASE));
That is shifting data 16 bits left into the most significant 16 bits of the word, shifting mem_addr up by 8 bits and or-ing it in, and then adding ERASE in the least significant bits.
Your problem is the Endianness.
By default the STM32 uses little edian so the lowest byte of the uint32_t is stored at the first adrress.
If I'm right this is the declaration if the transmit function you are using:
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
It requires a pointer to uint8_t as data (and not a uint32_t) so you should get at least a warning if you compile your code.
If you want to write code that is independent of the used endianess, you should store your data into an array instead of one "big" variable.
uint8_t write_package[4];
write_package[0] = ERASE;
write_package[1] = mem_addr;
write_package[2] = (data >> 8) & 0xFF;
write_package[3] = (data & 0xFF);

Invalid CRC32 Hash Generation

I'm creating SHA1 and CRC32 hash from plain text using Crypto++ Library as the following:
#include <cryptopp/filters.h>
#include <cryptopp/hex.h>
#include <cryptopp/sha.h>
#include <cryptopp/crc.h>
#include <string.h>
#include <iostream>
int main()
{
// Calculate SHA1
std::string data = "Hello World";
std::string base_encoded_string;
byte sha_hash[CryptoPP::SHA::DIGESTSIZE];
CryptoPP::SHA().CalculateDigest(sha_hash, (byte*)data.data(), data.size());
CryptoPP::StringSource ss1( std::string(sha_hash, sha_hash+CryptoPP::SHA::DIGESTSIZE), true,
new CryptoPP::HexEncoder( new CryptoPP::StringSink( base_encoded_string ) ));
std::cout << base_encoded_string << std::endl;
base_encoded_string.clear();
// Calculate CRC32
byte crc32_hash[CryptoPP::CRC32::DIGESTSIZE];
CryptoPP::CRC32().CalculateDigest(crc32_hash, (byte*)data.data(), data.size());
CryptoPP::StringSource ss2( std::string(crc32_hash, crc32_hash+CryptoPP::CRC32::DIGESTSIZE), true,
new CryptoPP::HexEncoder( new CryptoPP::StringSink( base_encoded_string ) ));
std::cout << base_encoded_string << std::endl;
base_encoded_string.clear();
}
The output I get is:
0A4D55A8D778E5022FAB701977C5D840BBC486D0
56B1174A
Press any key to continue . . .
And, out of these I confirmed that CRC32 is incorrect according to various online resources such as this one: http://www.fileformat.info/tool/hash.htm?text=Hello+World
I have no idea why because I'm creating CRC32 hash by following the same procedure as I followed for SHA1. Is there really different way or am I really doing something wrong in here?
byte crc32_hash[CryptoPP::CRC32::DIGESTSIZE];
I believe you have a bad endian interaction. Treat the CRC32 value is an integer, not a byte array.
So try this:
int32_t crc = (crc32_hash[0] << 0) | (crc32_hash[1] << 8) |
(crc32_hash[2] << 16) | (crc32_hash[3] << 24);
If crc32_hash is integer aligned, then you can:
int32_t crc = ntohl(*(int32_t*)crc32_hash);
Or, this might be easier:
int32_t crc32_hash;
CryptoPP::CRC32().CalculateDigest(&crc32_hash, (byte*)data.data(), data.size());
I might be wrong about int32_t, it might be uint32_t (I did not look at the standard).

Qt equivalent of Perl pack/unpack

The following is a list of hex data and the float numbers it represents:
e77ed8f8201a5440 = 78.4083
0000000000005540 = 82
4c541773e2185040 = 62.3888
0000000000005640 = 86
The following Perl code uses pack/unpack to gets the conversion almost right (out by exactly 2):
use strict;
use warnings;
while (<DATA>)
{
chomp;
my $dat = $_;
my $hval = pack "H*", $dat;
my $fval = unpack "F", $hval;
print "$dat .. $fval \n";
}
__DATA__
e77ed8f8201a5440
0000000000005540
4c541773e2185040
0000000000005640
Output:
e77ed8f8201a5440 .. 80.408262454435
0000000000005540 .. 84
4c541773e2185040 .. 64.3888213851762
0000000000005640 .. 88
What is the Qt/C equivalent of this pack/unpack, or what is the algorithm it is use to "convert" the hex to float so I can that up instead?
What is the Qt/C equivalent of this pack/unpack,
#include <QString>
#include <QByteArray>
#include <algorithm>
#include <cstring>
...
QString value="e77ed8f8201a5440";
// convert the hex string to an array of bytes
QByteArray arr=QByteArray::fromHex(value);
// reverse if necessary
#if Q_BYTE_ORDER==Q_BIG_ENDIAN
std::reverse(arr.begin(), arr.end());
#endif
// if everything went right, copy the bytes in a double
if(arr.size()==sizeof(double))
{
double out;
std::memcpy((void *)&out, (void *)arr.data(), sizeof(double));
// ...
}
Maybe you could also get away with QtEndian (instead of conditionally calling std::reverse over arr), but it's not clear if those functions can be called on anything but integral types.
or what is the algorithm it is use to "convert" the hex to float so I can that up instead?
The data you have is just the dump of the raw content of a little-endian IEEE-754 double; the "algorithm" is simply decoding the hexadecimal to the bytes it represents and copying them to a double variable (reversing the byte order if we are on a big-endian machine).
pack 'H*' is the conversion from hex character pairs to the corresponding bytes.
unpack 'F' is a cast to a double. This can be done using memcpy (to avoid alignment issues), as shown below:
#include <stdio.h>
#include <string.h>
int main() {
char bytes[] = { 0xE7, 0x7e, 0xd8, 0xf8, 0x20, 0x1a, 0x54, 0x40 };
double d;
memcpy(&d, bytes, sizeof(bytes));
printf("%lf\n", d);
return 0;
}
Output:
$ gcc -o a a.c && a
80.408262
Note that this will fail on big-endian machines. You'll have to reverse the bytes before copying them on those machines.

RAW RSA encryption and decryption with Crypto++

I need to establish a secure communication between a PC and a device which supports RSA encryption and signature with SHA1. As I have already used Crypto++ in other parts of my application, I would like to utilize Crypto++ for this as well.
The device is very primitive but allows executing a program I write on it. It has raw RSA and SHAa functions built-in; However, it has very little memory to work with, 2K bytes to be precise.
I have to encrypt and sign a message from a PC. Then the device decrypts and verifies the message. The device will then reply an encrypted message and sign on it. The PC will decrypt the message and verify it afterwards. I have implemented the raw RSA encryption, signature and verification with SHA1 inside the device using the built-in functions. The messages is short enough to be done in a single round.
However, I don't know how to encrypt a message with raw RSA using Crypto++ without involving OAEP or PKCS#1. Could somebody kind enough to show me some sample code? Thanks a ton!
I don't know how to encrypt a message with raw RSA using Crypto++ without
involving OAEP or PKCS#1. Could somebody kind enough to show me some sample code?
That's easy enough when you know where to look: Raw RSA from the Crypto++ wiki. The code below was taken from the page.
Encryption
Integer n("0xbeaadb3d839f3b5f"), e("0x11"), d("0x21a5ae37b9959db9");
RSA::PublicKey pubKey;
pubKey.Initialize(n, e);
///////////////////////////////////////////////////////////////
Integer m, c;
string message = "secret";
cout << "message: " << message << endl;
// Treat the message as a big endian byte array
m = Integer((const byte *)message.data(), message.size());
cout << "m: " << hex << m << endl;
// Encrypt
c = pubKey.ApplyFunction(m);
cout << "c: " << hex << c << endl;
Decryption
Integer n("0xbeaadb3d839f3b5f"), e("0x11"), d("0x21a5ae37b9959db9");
AutoSeededRandomPool prng;
RSA::PrivateKey privKey;
privKey.Initialize(n, e, d);
///////////////////////////////////////////////////////////////
Integer c("0x3f47c32e8e17e291"), r;
string recovered;
// Decrypt
r = privKey.CalculateInverse(prng, c);
cout << "r: " << hex << r << endl;
// Round trip the message
size_t req = r.MinEncodedSize();
recovered.resize(req);
r.Encode((byte *)recovered.data(), recovered.size());
cout << "recovered: " << recovered << endl;
Here's a sample output:
$ ./cryptopp-raw-rsa.exe
message: secret
m: 736563726574h
c: 3f47c32e8e17e291h
r: 736563726574h
recovered: secret
There is one caveat: c = m ^ e mod n, so there are some limits on plaint text size and cipher text size. Essentially, m and c must be smaller than n. In this example, replacing the string secret with now is the time for all good men to come to the aid of their country would fail because it's larger than n when converted to an Integer.
You can get the maximum plain text size with the function MaxPreImage(), and the maximum cipher text size with MaxImage().
I have to encrypt and sign a message from a PC. Then the device decrypts
and verifies the message. The device will then reply an encrypted message
and sign on it. The PC will decrypt the message and verify it afterwards.
On the surface, this looks like it will suffer replay attacks. You might need a protocol with the protection.
Here is a demo function I wrote when I first did RSA encryption and decryption with Crypto++. I wrote it just to understand the basics. I hope it helps:
#include <cryptopp/files.h>
#include <cryptopp/modes.h>
#include <cryptopp/osrng.h>
#include <cryptopp/rsa.h>
#include <cryptopp/sha.h>
using namespace CryptoPP;
void rsa_examples()
{
// Keys created here may be used by OpenSSL.
//
// openssl pkcs8 -in key.der -inform DER -out key.pem -nocrypt
// openssl rsa -in key.pem -check
AutoSeededRandomPool rng;
// Create a private RSA key and write it to a file using DER.
RSAES_OAEP_SHA_Decryptor priv( rng, 4096 );
TransparentFilter privFile( new FileSink("rsakey.der") );
priv.DEREncode( privFile );
privFile.MessageEnd();
// Create a private RSA key and write it to a string using DER (also write to a file to check it with OpenSSL).
std::string the_key;
RSAES_OAEP_SHA_Decryptor pri( rng, 2048 );
TransparentFilter privSink( new StringSink(the_key) );
pri.DEREncode( privSink );
privSink.MessageEnd();
std::ofstream file ( "key.der", std::ios::out | std::ios::binary );
file.write( the_key.data(), the_key.size() );
file.close();
// Example Encryption & Decryption
InvertibleRSAFunction params;
params.GenerateRandomWithKeySize( rng, 1536 );
std::string plain = "RSA Encryption", cipher, decrypted_data;
RSA::PrivateKey privateKey( params );
RSA::PublicKey publicKey( params );
RSAES_OAEP_SHA_Encryptor e( publicKey );
StringSource( plain, true, new PK_EncryptorFilter( rng, e, new StringSink( cipher )));
RSAES_OAEP_SHA_Decryptor d( privateKey );
StringSource( cipher, true, new PK_DecryptorFilter( rng, d, new StringSink( decrypted_keydata )));
assert( plain == decrypted_data );
}