Secret from Gogs hook (failing to get on python3)


#1

Gogs Versión: 0.11.66.0916 on SQLite

I’m configuring a gogs hook, I have an API that receives this POST from push
e.g.

secret: myS3cr3t

it’s supposed that " Secret will be sent as SHA256 HMAC hex digest of payload via X-Gogs-Signature header."

then in python3 I got it like this:

message is the payload (json body) from the request and the key i set it on env var

import hashlib
import hmac

def get_secret_signature(message, secret):
   signature = hmac.new(bytes(key, 'utf-8'), bytes(message, 'utf-8'), hashlib.sha256).hexdigest()
   return signature 

but when checking the hook is failing cause the signature sent in X-Gogs-Signature never match with the signature generated on python


#2

Hi,

Have you checked the actual value from Gogs and compare it with some online tool?


#3

Checked it here https://www.freeformatter.com/hmac-generator.html
but i’m not sure if this site gave me the hex digest, and couldn’t find a site that can give me exactly that

but even checking the jenkins plugin for gogs, the method to get the signature:

public static String encode(String data, String key) throws Exception {
    final Charset asciiCs = Charset.forName("UTF-8");
    final Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
    final SecretKeySpec secret_key = new javax.crypto.spec.SecretKeySpec(asciiCs.encode(key).array(), "HmacSHA256");
    sha256_HMAC.init(secret_key);
    return Hex.encodeHexString(sha256_HMAC.doFinal(data.getBytes("UTF-8")));
}

I think it’s the same logic in python, obviously shorter in python :stuck_out_tongue:

so the signature is made only from secret used as key and the payload made from JSON body?


#4

Based on the following code, I think yes.

But sometimes, you need to be careful handling last EOL character, single bit of change produces different hash output.


#5

Yep, that was the problem, it seems that the variable that had the payload was not escaping some characters, since I’m using the python framework Bottle this is the right way to get the payload:

payload = request._get_body_string()
gogs_signature = request.get_header('X-Gogs-Signature')

signature = get_secret_signature(payload, secret)
.
.
.
if gogs_signature != signature:
   print("Signature error")

def get_secret_signature(message, secret):
   signature = hmac.new(bytes(key, 'utf-8'), message, hashlib.sha256).hexdigest()
   return signature

thank you :+1: greetings from :mexico: