TDR
TDR

Reputation: 21

PHP - Encryption and signature creation for web service

I need to create a "secret key" with PHP in order to consume a web service but it's making little sense to me.

The web service has been shown to work with a C# application but I need to access it via PHP.

In order to consume the service I need a "secret key" and then an authentication signature based on that key.

Everything I've tried just throws an error from the web service.

For the "secret key", the brief is:

  1. ASCII encode a plain text password
  2. Hash the encoded password using MD5
  3. Get MD5 hash bytes and perform bit wise operation ‘& 127’
  4. Convert to base64 string

It's point 3 that's unclear to me - the rest is pretty straight forward; what am I missing here?

Then to generate the authentication signature the brief is:

  1. UTF-8 Encoding of secret key (Secret access key is the result of step 4)
  2. UTF-8 Encoding of date
  3. HMAC-SHA1 (UTF-8-Encoding-Of (Secret access key, RequestDate))
  4. Base 64 string

Again, no issues that I can see with the above - it's just the point 3 that's throwing me.

Any pointers?

Upvotes: 2

Views: 697

Answers (1)

Scott Arciszewski
Scott Arciszewski

Reputation: 34123

It's point 3 that's unclear to me - the rest is pretty straight forward; what am I missing here?

The signature algorithm you're describing is far from secure. You'd be better off with Ed25519 (via sodium_crypto_sign_detached() and sodium_crypto_sign_verify_detached()) instead of this MD5 and SHA1 nonsense.

That being said, they're probably expecting something like this:

function insecureMd5Kdf($message, $raw = false)
{
    $bytes = md5($message, true);
    $output = '';
    for ($i = 0; $i < 16; ++$i) {
        $int = ord($bytes[$i]) & 127;
        $output .= pack('C', $int);
    }
    if (!$raw) {
        return bin2hex($output);
    }
    return $output;
}

Demo here.

Why would anyone do this?

Specifically:

Get MD5 hash bytes and perform bit wise operation ‘& 127’

In Java, bytes can range from -128 to 127. Using the & 127 operator clears the higher bit, reducing the range of possible values to [0, 127].

The answer, I suspect, is "lazy programming". That is to say, someone wanted a quick workaround to a discrepancy between Java and PHP and clearing out the high bit of each byte of the MD5 hash saved them from having to convert numbers in the [128, 255] range to [-128, -1].

If this web service is still around, you should ask them for their latest security audit results.

Upvotes: 3

Related Questions