Skip to content

Instantly share code, notes, and snippets.

@hotrungnhan
Last active December 18, 2025 05:56
Show Gist options
  • Select an option

  • Save hotrungnhan/b04de71f44df1db2d87b8b6bb492f175 to your computer and use it in GitHub Desktop.

Select an option

Save hotrungnhan/b04de71f44df1db2d87b8b6bb492f175 to your computer and use it in GitHub Desktop.
package main
import (
"bufio"
"fmt"
"os"
)
var in = bufio.NewReader(os.Stdin)
func power4(x int64) int64 {
return x * x * x * x
}
func recursiveReadAndSumPower4Numbers(x int, sum *int64) {
if x == 0 {
return
}
var y int64
fmt.Fscan(in, &y)
if y <= 0 {
*sum += power4(y)
}
recursiveReadAndSumPower4Numbers(x-1, sum)
}
func recursiveProcessTests(t int) {
if t == 0 {
return
}
var x int
fmt.Fscan(in, &x)
var sum int64 = 0
recursiveReadAndSumPower4Numbers(x, &sum)
fmt.Println(sum)
recursiveProcessTests(t - 1)
}
func main() {
var t int
fmt.Fscan(in, &t)
recursiveProcessTests(t)
}
import crypto from "crypto";
function totpHex(secretHex, counter, algo, digits = 8) {
const msg = Buffer.alloc(8);
msg.writeBigUInt64BE(BigInt(counter));
const hmac = crypto
.createHmac(algo, Buffer.from(secretHex, "hex"))
.update(msg)
.digest();
const offset = hmac[hmac.length - 1] & 0x0f;
const code =
((hmac[offset] & 0x7f) << 24) |
((hmac[offset + 1] & 0xff) << 16) |
((hmac[offset + 2] & 0xff) << 8) |
(hmac[offset + 3] & 0xff);
return (code % 10 ** digits).toString().padStart(digits, "0");
}
// test part
const seed =
"3132333435363738393031323334353637383930";
const seed32 =
seed + "313233343536373839303132";
const seed64 =
seed +
"3132333435363738393031323334353637383930" +
"3132333435363738393031323334353637383930" +
"31323334";
const times = [
59,
1111111109,
1111111111,
1234567890,
2000000000,
20000000000
];
const X = 30;
for (const t of times) {
const counter = Math.floor(t / X);
const hexT = counter.toString(16).toUpperCase().padStart(16, "0");
console.log("Time:", t);
console.log("T(hex):", hexT);
console.log("SHA1 :", totpHex(seed, counter, "sha1"));
console.log("SHA256:", totpHex(seed32, counter, "sha256"));
console.log("SHA512:", totpHex(seed64, counter, "sha512"));
console.log("----");
}
@hotrungnhan
Copy link
Author

hotrungnhan commented Dec 16, 2025

EMAIL=""
GITHUB_PATH=""
OTP=""
curl -X POST \
  https://api.challenge.hennge.com/challenges/backend-recursion/004 \
  -H "Content-Type: application/json" \
  -H "Authorization: Basic $(printf '%s:%s' "$EMAIL" "$OTP" | base64)" \
  -d "{
    \"github_url\": \"https://gist.github.com/$GITHUB_PATH\",
    \"contact_email\": \"$EMAIL\",
    \"solution_language\": \"golang\"
  }"

@hotrungnhan
Copy link
Author

hotrungnhan commented Dec 16, 2025

Quick way to double verify otpauth implementation.

import * as OTPAuth from "otpauth";


function generateHenngeTOTP(email) {
  const secretString = email + "HENNGECHALLENGE004";

  const totp = new OTPAuth.TOTP({
    issuer: "HENNGE",
    label: email,
    algorithm: "SHA512",
    digits: 10,
    period: 30,
    secret: OTPAuth.Secret.fromUTF8(secretString),
  });

  return totp.generate();
}

const email = "[email protected]";
const otp = generateHenngeTOTP(email);

console.log("TOTP:", otp);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment