OpenAI-Sentinel-Proof-Token 生成算法分析

之前水了一篇ChatGPT上PoW的帖子。有佬友问 OpenAI-Sentinel-Proof-Token 怎么生成。我再来水一篇。

async _getAnswer(e)
{
    var t,
        n;
    if (!(null != e && null !== (t = e.proofofwork) && void 0 !== t && t.required))
        return null;
    let {seed: a, difficulty: r} = e.proofofwork;
    return "string" == typeof a && "string" == typeof r ? "gAAAAAB" + (null !== (n = this.answers.get(a)) && void 0 !== n ? n : await this._generateAnswer(a, r)) : null
}
async _generateAnswer(e, t)
{
    let n = "e";
    try {
        let n = null,
            a = this.getConfig();
        for (let s = 0; s < this.maxAttempts; s++) {
            (!n || 0 >= n.timeRemaining()) && (n = await new Promise(e => {
                (window.requestIdleCallback || function(e) {
                    return setTimeout(() => {
                        e({
                            timeRemaining: () => 1,
                            didTimeout: !1
                        })
                    }, 0), 0
                })(t => {
                    e(t)
                })
            })),
            a[3] = s;
            let o = i(a);
            if ((await (0, r.ki)(e + o)).substring(0, t.length) <= t)
                return this.answers.set(e, o), o
        }
    } catch (e) {
        n = i("" + e)
    }
    return "wQ8Lk5FbGpA2NcR9dShT6gYjU7VxZ4D" + n
}
getConfig()
{
    var e,
        t,
        n,
        a,
        r;
    return [(null === (e = navigator) || void 0 === e ? void 0 : e.hardwareConcurrency) + (null === (t = screen) || void 0 === t ? void 0 : t.width) + (null === (n = screen) || void 0 === n ? void 0 : n.height), "" + new Date, null === (a = performance) || void 0 === a || null === (a = a.memory) || void 0 === a ? void 0 : a.jsHeapSizeLimit, null == Math ? void 0 : Math.random(), null === (r = navigator) || void 0 === r ? void 0 : r.userAgent]
}

function i(e) {
	return (e = JSON.stringify(e), window.TextEncoder) ? btoa(String.fromCharCode(...new TextEncoder().encode(e))) : btoa(unescape(encodeURIComponent(e)))
}

主要的js代码在这里。首先看看是不是需要PoW,不需要就不说了。

接下来取 seed 和 difficulty 参数去碰撞。最后拿碰撞的答案 gAAAAAB + base64(answer)

answer 生成在 _generateAnswer 中,简单来说就是用 getConfig() 生成字符串,大概是:

[1850,"Fri Apr 19 2024 11:51:38 GMT+0800 (中国标准时间)",null,46,"<user agent>"]

这种,具体看js代码。比如第一个参数就是 navigator.hardwareConcurrency+screen.width+screen.height

然后拿这个字符串base64之后,在前面放seed,形成如:0.2616356464867712WzE4MDMsIkZyaSBBcHxxxx 这样的字符串。

重点来了,这个js里隐藏了hash算法,跟进去也是wasm的,但其实hash算法是 SHA3-512

算出来hash截取 difficulty 的长度来跟 difficulty 比较即可。符合就返回这个 base64 的字符串,跟 gAAAAAB 拼接成最终 OpenAI-Sentinel-Proof-Token。否则就重复这个过程。

最终撞不撞的到,看 getConfig() 里的 Math.random() 灵不灵了。最多撞 this.maxAttempts 也就是 10w 次。

这帖不值5分???

163 个赞

沙发,看不懂

4 个赞

终于第一了

第一被抢了

:sob::sob::sob:

4 个赞

那我两分

1 个赞

前排,看不懂

1 个赞

看不懂

开始学习

吾皇高产~~新人友好贴,赞!就喜欢这样深入浅出的

2 个赞

分析贴这么快就上了 :+1:

1 个赞

看不懂思密达,来个高材生解释一下

1 个赞

这贴还真不止5分~~

1 个赞

佬!

始皇一水,水中之水!

厉害,这么快就出来了。

openai该收手了,根本斗不过始皇

1 个赞

汉字都认识,连一起就不知道啥意思了

你 5 我 2

1 个赞

看不懂,但是觉得好厉害,膜拜吾皇

牛哇牛哇

我们web3就是强