08-05-2010 7:13 PM
Not sure whether I'm in the correct forum...
To sign a message for a specific application with HMAC-SHA1 hash I need a 83 character key.
My problem: the function module 'SET_HMAC_KEY' throws the exception "param_length_error". After I've testet with several key length, I found out, that the maximum valid length is 81. Is there any reason for this?
With 3rd party libraries (ie. Python and Javascript) longer keys are working.
Code:
CALL FUNCTION 'SET_HMAC_KEY'
EXPORTING
generate_random_key = ' '
alg = 'SHA1'
keycstr = 'cB1phTHISISATESTVuZMDmWCz1CEMy82iBC3HgFLpE&7857T...YFqV93gRJQ'
client_independent = ' '
EXCEPTIONS
unknown_alg = 1
param_length_error = 2
internal_error = 3
param_missing = 4
malloc_error = 5
abap_caller_error = 6
base64_error = 7
calc_hmac_error = 8
rsec_record_access_denied = 9
rsec_secstore_access_denied = 10
rsec_error = 11
rng_error = 12
record_number_error = 13
OTHERS = 14.
Best regards, Uwe
Edited by: Julius Bussche on Aug 5, 2010 10:19 PM
I truncated the key further because in a coding tag it toasts the formatting when too long.
08-06-2010 12:30 AM
Hi,
that number 81 seems completly random to me. 81 characters (bytes) is 648 bits. Here is a quote from [RFC 2104 - HMAC: Keyed-Hashing for Message Authentication|http://www.faqs.org/rfcs/rfc2104.html].
The key for HMAC can be of any length (keys longer than B bytes are
first hashed using H). However, less than L bytes is strongly
discouraged as it would decrease the security strength of the
function. Keys longer than L bytes are acceptable but the extra
length would not significantly increase the function strength. (A
longer key may be advisable if the randomness of the key is
considered weak.)
So there is no limit for key size but any key longer than block size (B bytes) of hash function will be compressed to B bytes. The key should be longer than output size of has function (L bytes) which for SHA-1 is 160 bits = 20 bytes. The internal state of SHA-1 is 512bits == 64 bytes.
So I would suggest that to use SHA-1 functin to reduce any key longer than 64 bytes to 64 bytes and then to pass a new key to SET_HMAC_KEY.
Cheers
08-05-2010 7:16 PM
I dont know if all would agree on this:
This seems to be a development question.
08-05-2010 7:22 PM
Hi Franklin,
Forum description:
...secure collaboration, such as message security (encryption) and trust management...
Regards, Uwe
08-05-2010 7:51 PM
08-05-2010 8:16 PM
I'm not sure if this helps, but if you look at http://en.wikipedia.org/wiki/HMAC you will see following text:
The size of the output of HMAC is the same as that of the underlying hash function (128 or 160 bits in the case of MD5 or SHA-1, respectively),
Of course, this doesn't mean that any library included with SAP product, or added as a third-party crypto library will support the full 160-bits (20 bytes)
Also, I think you will find that the encryption alg used with HMAC-SHA1 will determine the key length, not the hash alg.
Thanks,
Tim
08-05-2010 8:34 PM
Hi Tim,
that's what makes me astonished. Not the encryption FM 'CALCULATE_HMAC_FOR_CHAR' I'm using later in my app is the problem, but the simple setter method 'SET_HMAC_KEY'.
Uwe
08-05-2010 8:43 PM
If you look at the wikipedia page I referenced earlier, you will see it shows:
function hmac (key, message)
if (length(key) > blocksize) then
key = hash(key) // keys longer than blocksize are shortened
end if
if (length(key) < blocksize) then
key = key u2225 zeroes(blocksize - length(key)) // keys shorter than blocksize are zero-padded
end if
So, you just need to know what the blocksize is and then you will know what max key size can be input into hmac alg. If the key used is larger it will be shortened, and if shorter it will be zero padded to make it same as blocksize.
I think for sha-1 the block size is 64, so this should be the max key length for hmac. I found a useful explanation at http://stackoverflow.com/questions/3341167/how-to-implement-hmac-sha1-algorithm-in-qt
Thanks,
Tim
08-05-2010 9:18 PM
Note that the functions are not released and encapsulate a kernel-function to write the key into the SecureStorage area - there will be no publicly available information on these as far as I am aware and are insecure to use (from a stability perspective).
What is publicly known about the SecureStorage area is that the call-stacks are protected to access the data again (particularly to decrypt) so I can't see how this would work in your own application because even within SAP only special programs are allowed to call the functions.
What data is the application trying to store? A password? Possibly there is a better way to deal with it in a secure manner.
Have you looked into the SSF (Secure Store & Forward) because you mentioned "signing a message"?
Cheers,
Julius
Edited by: Julius Bussche on Aug 5, 2010 10:21 PM
08-05-2010 9:26 PM
Hi Julius,
I'm using 'CALCULATE_HMAC_FOR_CHAR' to sign messages (OAuth) and it works great until the encryption key is less than 82 chars.
Since the documentation for the function group SECH is rolled out in 7.01 sp07 (note 1416202) I thought the usage of these function mudules is secure (lol) and allowed.
Regards, Uwe
08-05-2010 9:33 PM
Ahh.. I'm on 7.01 SP 6...
Thanks for the info though!
I will ping someone for you to take a look into this import parameter option. Is it not mentioned in the documentation?
Cheers,
Julius
08-05-2010 10:00 PM
08-06-2010 12:30 AM
Hi,
that number 81 seems completly random to me. 81 characters (bytes) is 648 bits. Here is a quote from [RFC 2104 - HMAC: Keyed-Hashing for Message Authentication|http://www.faqs.org/rfcs/rfc2104.html].
The key for HMAC can be of any length (keys longer than B bytes are
first hashed using H). However, less than L bytes is strongly
discouraged as it would decrease the security strength of the
function. Keys longer than L bytes are acceptable but the extra
length would not significantly increase the function strength. (A
longer key may be advisable if the randomness of the key is
considered weak.)
So there is no limit for key size but any key longer than block size (B bytes) of hash function will be compressed to B bytes. The key should be longer than output size of has function (L bytes) which for SHA-1 is 160 bits = 20 bytes. The internal state of SHA-1 is 512bits == 64 bytes.
So I would suggest that to use SHA-1 functin to reduce any key longer than 64 bytes to 64 bytes and then to pass a new key to SET_HMAC_KEY.
Cheers
08-06-2010 11:37 AM
Hi Martin,
So I would suggest that to use SHA-1 functin to reduce any key longer than 64 bytes to 64 bytes and then to pass a new key to SET_HMAC_KEY.
Unfortunatelly I cannot cut the key.
The definition of the [HMAC-SHA1 OAuth key|http://tools.ietf.org/html/rfc5849#page-25] according RFC 5849:
key is set to the concatenated values of:
1. The client shared-secret, after being encoded
(Section 3.6).
2. An "&" character (ASCII code 38), which MUST be included
even when either secret is empty.
3. The token shared-secret, after being encoded
(Section 3.6).
And the result in my case is a string of 83 characters.
Regards, Uwe
08-06-2010 1:32 PM
Hi,
yes, we can :-). Let say that SAP implementation supports a key with size more than 81 bytes. Then according to specification if the key is longer than block size of hash function (64 bytes for SHA-1) then it would use hash function to reduce original key to new key with size equals to output size of hash function (20 bytes for SHA-1). Therefore doing this step manually before calling SET_HMAC_KEY is equal to calling SET_HMAC_KEY which supports keys longer than 81 bytes.
The easiest way how to check this is to compare some HMAC-SHA1 implementation with the result produced by my proposed logic.
DATA: text TYPE string,
key_str TYPE string,
hash TYPE hash160x,
key TYPE xstring,
hmac TYPE hash512_base_64.
text = 'Hello'.
key_str = '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789'.
CALL FUNCTION 'CALCULATE_HASH_FOR_CHAR'
EXPORTING
data = key_str
IMPORTING
hashx = hash.
key = hash.
CALL FUNCTION 'SET_HMAC_KEY'
EXPORTING
generate_random_key = space
alg = 'SHA1'
keyxstr = key
client_independent = space.
CALL FUNCTION 'CALCULATE_HMAC_FOR_CHAR'
EXPORTING
alg = 'SHA1'
data = text
IMPORTING
hmacbase64 = hmac.
WRITE: / hmac.
Javascript version
var hmac = Crypto.HMAC(Crypto.SHA1, "Message", "Secret Passphrase");
var hmacBytes = Crypto.HMAC(Crypto.SHA1, "Message", "Secret Passphrase", { asBytes: true });
var hmacString = Crypto.HMAC(Crypto.SHA1, "Message", "Secret Passphrase", { asString: true });
Both implementations return "qsXNz/wecK4PMob6VG9RyRX6DQI=".
Cheers
Sorry for formatting but it looks like something is broken.
Edited by: Martin Voros on Aug 6, 2010 10:34 PM
08-06-2010 2:14 PM
Martin, BIIIINGO -> that's it!!!
Great, thank you very much, you saved my day.
Take a beer on my bill
Uwe