I'm working with a payment provider which uses the following algorithm for signing messages:
- The merchant is securely given a secret key
k
, known to them and the payment provider only. EDIT: Usually the key is quite long. The payment is implemented by using a redirect, and the merchant later receives callbacks containing information about the success or failure of the payment operation. The merchant considers this information trustworthy. Here is an example of a successful payment callback for order no. 1234 and a merchant hosted at
example.com
:example.com?orderID=1234&paymentStatus=SUCCESS&...&signature=abcd
The message
m
which is signed is formed in the following way:orderid=<..>|paymentStatus=<..>|...
The signature algorithm
S(m,k)
is chosen to be:signature=H(m||k)
(m||k
meansm
concatenated with the secret keyk
) whereH
is a hashing function, in this caseMD5
.- The verification algorithm is
V(signature, m, k)
and returns true only ifH(m||k) = signature
.
As far as I understood the inner workings of MD5 if the signing algorithm was S(m,k) = H(k||m)
then this would be totally insecure because if an attacker knows H(k||m)
she may be able to calculate H(k||m||m')
where m'
is a message of her choice - this would mean that the signature is vulnerable to both existential and selective forgery. Correct? But deliberately or not the algorithm is S(m,k) = H(m||k)
- the key is put last in the concatenated string.
So far I cannot think of exploitable vulnerability in this protocol (I'm not considering the problems inherent to MD5). Any ideas, is this secure enough?
MD5(k||m)
allows computingMD5(k||m||m'||m")
form'
a certain known function ofm
and the length ofk
(withm'
at least 9 bytes or 65 bits), and freely chosenm"
. – fgrieu Nov 13 '14 at 09:58