package bech32encoding import ( "bytes" "smesh.lol/pkg/nostr/ec/bech32" "smesh.lol/pkg/nostr/ec/schnorr" "smesh.lol/pkg/nostr/ec/secp256k1" "smesh.lol/pkg/nostr/hex" "smesh.lol/pkg/lol/chk" "smesh.lol/pkg/lol/log" ) const ( MinKeyStringLen = 56 HexKeyLen = 64 Bech32HRPLen = 4 ) var ( SecHRP = []byte("nsec") PubHRP = []byte("npub") ) func ConvertForBech32(b8 []byte) (b5 []byte, err error) { return bech32.ConvertBits(b8, 8, 5, true) } func ConvertFromBech32(b5 []byte) (b8 []byte, err error) { return bech32.ConvertBits(b5, 5, 8, true) } func SecretKeyToNsec(sk *secp256k1.SecretKey) (encoded []byte, err error) { var b5 []byte if b5, err = ConvertForBech32(sk.Serialize()); chk.E(err) { return } return bech32.Encode(SecHRP, b5) } func PublicKeyToNpub(pk *secp256k1.PublicKey) (encoded []byte, err error) { var bits5 []byte pubKeyBytes := schnorr.SerializePubKey(pk) if bits5, err = ConvertForBech32(pubKeyBytes); chk.E(err) { return } return bech32.Encode(PubHRP, bits5) } func NsecToSecretKey(encoded []byte) (sk *secp256k1.SecretKey, err error) { var b8 []byte if b8, err = NsecToBytes(encoded); chk.E(err) { return } sk = secp256k1.SecKeyFromBytes(b8) return } func NsecToBytes(encoded []byte) (sk []byte, err error) { var b5, hrp []byte if hrp, b5, err = bech32.Decode(encoded); chk.E(err) { return } if !bytes.Equal(hrp, SecHRP) { err = log.E.Err([]byte("wrong human readable part, got '%s' want '%s'"), hrp, SecHRP) return } if sk, err = ConvertFromBech32(b5); chk.E(err) { return } sk = sk[:secp256k1.SecKeyBytesLen] return } func NpubToBytes(encoded []byte) (pk []byte, err error) { var b5, hrp []byte if hrp, b5, err = bech32.Decode(encoded); chk.E(err) { return } if !bytes.Equal(hrp, PubHRP) { err = log.E.Err([]byte("wrong human readable part, got '%s' want '%s'"), hrp, PubHRP) return } if pk, err = ConvertFromBech32(b5); chk.E(err) { return } pk = pk[:schnorr.PubKeyBytesLen] return } func NpubToPublicKey(encoded []byte) (pk *secp256k1.PublicKey, err error) { var b5, b8, hrp []byte if hrp, b5, err = bech32.Decode(encoded); chk.E(err) { return } if !bytes.Equal(hrp, PubHRP) { err = log.E.Err([]byte("wrong human readable part, got '%s' want '%s'"), hrp, PubHRP) return } if b8, err = ConvertFromBech32(b5); chk.E(err) { return } return schnorr.ParsePubKey(b8[:schnorr.PubKeyBytesLen]) } func HexToPublicKey(pk []byte) (p *secp256k1.PublicKey, err error) { if len(pk) != HexKeyLen { err = log.E.Err([]byte("key is %d bytes, must be %d"), len(pk), HexKeyLen) return } var pb []byte if pb, err = hex.Dec(string(pk)); chk.D(err) { return } return schnorr.ParsePubKey(pb) } func HexToNpub(publicKeyHex []byte) (s []byte, err error) { b := []byte{:schnorr.PubKeyBytesLen} if _, err = hex.DecBytes(b, publicKeyHex); chk.D(err) { return } var bits5 []byte if bits5, err = bech32.ConvertBits(b, 8, 5, true); chk.D(err) { return } return bech32.Encode(NpubHRP, bits5) } func BinToNpub(b []byte) (s []byte, err error) { var bits5 []byte if bits5, err = bech32.ConvertBits(b, 8, 5, true); chk.D(err) { return } return bech32.Encode(NpubHRP, bits5) } func HexToSecretKey(sk []byte) (s *secp256k1.SecretKey, err error) { if len(sk) != HexKeyLen { err = log.E.Err([]byte("secret key is %d bytes, must be %d"), len(sk), HexKeyLen) return } pb := []byte{:schnorr.PubKeyBytesLen} if _, err = hex.DecBytes(pb, sk); chk.D(err) { return } s = secp256k1.SecKeyFromBytes(pb) return } func HexToNsec(sk []byte) (nsec []byte, err error) { var s *secp256k1.SecretKey if s, err = HexToSecretKey(sk); chk.E(err) { return } return SecretKeyToNsec(s) } func BinToNsec(sk []byte) (nsec []byte, err error) { s := secp256k1.SecKeyFromBytes(sk) return SecretKeyToNsec(s) } func SecretKeyToHex(sk *secp256k1.SecretKey) (hexSec []byte) { return hex.EncAppend(nil, sk.Serialize()) } func NsecToHex(nsec []byte) (hexSec []byte, err error) { var sk *secp256k1.SecretKey if sk, err = NsecToSecretKey(nsec); chk.E(err) { return } return SecretKeyToHex(sk), nil }