# Emit pinSHA256 (hex) in Hysteria2 subscription links

**URL:** https://f.docs.rw/t/topic/346
**Category:** Предложения
**Tags:** done
**Created:** 2026-07-02T19:16:34Z
**Posts:** 7

## Post 1 by @Andy_2584 — 2026-07-02T19:16:34Z

## **Environment**

- Panel / backend: **2.8.0**
- Node: **2.8.0** , core: rw-core / Xray-core **26.6.27**
- Client tested: **Happ** (bundled core)

## **What we’d like**

When a Hysteria2 inbound uses an **inline self-signed certificate** and the host has `pinnedPeerCertSha256` set, please **add the certificate pin to the generated subscription** so that strict clients can validate the connection **without enabling `insecure`**.

Per the [Hysteria2 URI scheme](https://v2.hysteria.network/docs/developers/URI-Scheme/), the server certificate pin is passed as `pinSHA256=<hex-sha256>`. Today the base64 subscription (XRAY\_BASE64) omits this parameter, so the pin configured on the host never reaches the client.

## **Current output (base64 subscription)**

```
hysteria2://<uuid>@<ip>:443/?sni=www.twinmotion.com&fm=%7B%22quicParams%22%3A%7B%22debug%22%3Afalse%2C%22congestion%22%3A%22bbr%22%7D%7D#<name>
```

→ no `pinSHA256`, no `insecure` → strict clients can’t validate the self-signed cert.

## **Desired output (verified to work in Happ — cert accepted, no insecure)**

```
hysteria2://<uuid>@<ip>:443/?security=tls&sni=www.twinmotion.com&fm=...&insecure=0&pinSHA256=<HEX_SHA256_OF_LEAF_CERT>#<name>
```

i.e. hex-encode the host’s `pinnedPeerCertSha256` and add it as `pinSHA256` (hex, per the Hysteria2 URI spec). This lets self-signed Hysteria2 work out of the box, no manual insecure.

## **Note on XRAY\_JSON (encoding mismatch to consider)**

With `serveJsonAtBaseSubscription=true`, XRAY\_JSON emits `tlsSettings.pinnedPeerCertSha256` in **base64** (e.g. `hLzIuDGgIzwCNP1YbnFz14PXIYwR966VK6PEkZCD/lE=`). Happ’s bundled Xray core **hex-decodes** this field and fails to build the TLS config:

```
infra/conf: Failed to build TLS config. > encoding/hex: invalid byte: U+0068 'h'
```

Encoding differs by context: Xray-core v26.1.23 uses **base64** for `pinnedPeerCertSha256` in xray-json `tlsSettings`, while the Hysteria2 **URI** spec uses **hex** for `pinSHA256`. It would help to emit the correct encoding per output format (hex for the URI).

## **Steps to reproduce the current behavior**

1. Hysteria2 inbound with inline self-signed cert (e.g. [CN=www.twinmotion.com](http://CN=www.twinmotion.com)), `alpn: ["h3"]`, congestion bbr.
2. Host with `pinnedPeerCertSha256` (base64) set, `securityLayer=TLS`, sni, alpn h3.
3. Add the inbound to a squad; assign to a user.
4. Fetch the base64 subscription (client UA + `x-hwid`), base64-decode → the `hysteria2://` line has **no** `pinSHA256`.

## **Why it matters**

Self-signed Hysteria2 is a stateless, domain-free setup (no ACME needed). Emitting the pin the client already trusts would make it usable in strict clients (e.g. Happ) without insecure — the pin is already configured on the host and only needs to be serialized into the link.

---

## Post 2 by @remnawave — 2026-07-02T19:24:40Z

> [@Andy_2584](#):
>
> XRAY\_JSON emits `tlsSettings.pinnedPeerCertSha256`

The panel does not generate this field. You set it yourself in the “Advanced” host settings.

---

## Post 3 by @remnawave — 2026-07-02T19:26:01Z

> **[TLS | Project X](https://xtls.github.io/config/transports/tls.html)**
>
> Xray-core

 ![image](https://f.docs.rw/uploads/default/original/1X/b61db7b7b49c8ebe490688993f02fa0089265191.png)

---

## Post 4 by @remnawave — 2026-07-02T19:27:36Z

So the only possible reason why you have base64 in this field is because you yourself wrote such a value there.

---

## Post 5 by @remnawave — 2026-07-02T19:34:56Z

> <https://github.com/remnawave/backend/commit/4856dab28c0892a4e067c2948dc88229c74f1044>

`pinSHA256` was added. **Please note, it just use the value from “Advanced” host section. it does not generate or modify it. The same applies to Xray-Json.**

---

## Post 6 by @Andy_2584 — 2026-07-03T05:36:44Z

Thank you for the quick fix and the clarification — that makes sense.

Could you tell me which release will include commit `4856dab` (“add pinnedPeerCertSha256 support in hysteria2 base64 share-link”)? Is it planned for the next stable release (e.g. 2.8.1 / 2.9.0), and is there a rough ETA? I’d prefer to wait for a tagged release rather than run the `dev` image on a production panel.

One detail I’d like to confirm, since the value is passed through verbatim: the Hysteria2 URI scheme expects `pinSHA256` in **hex** , while the “Advanced” host field currently holds the **base64** SHA-256. Should I store the pin as hex in the Advanced field so it ends up as `pinSHA256=<hex>` in the link, or will the panel take care of the encoding?

Thanks again for the great work!

---

## Post 7 by @remnawave — 2026-07-03T11:46:34Z

Next release, probably 2.8.1.

> [@Andy_2584](#):
>
> One detail I’d like to confirm, since the value is passed through verbatim: the Hysteria2 URI scheme expects `pinSHA256` in **hex** , while the “Advanced” host field currently holds the **base64** SHA-256. Should I store the pin as hex in the Advanced field so it ends up as `pinSHA256=<hex>` in the link, or will the panel take care of the encoding?

As I mentioned above, the panel doesn’t modify or encode the values you specify. If you need hex, you must specify the hex value in the “Advanced” tab.

---

## Post 8 by @system — 2026-07-05T11:47:04Z

Эта тема была автоматически закрыта через 2 дня после последнего ответа. В ней больше нельзя отвечать.
