revising aliases ec, encryption
This commit is contained in:
@@ -8,14 +8,15 @@ import (
|
||||
"strings"
|
||||
|
||||
"lukechampine.com/frand"
|
||||
|
||||
"realy.lol/hex"
|
||||
"realy.lol/p256k"
|
||||
)
|
||||
|
||||
// ComputeSharedSecret returns a shared secret key used to encrypt messages. The private and public keys should be hex
|
||||
// encoded. Uses the Diffie-Hellman key exchange (ECDH) (RFC 4753).
|
||||
func ComputeSharedSecret(pkh, skh st) (sharedSecret by, err er) {
|
||||
var skb, pkb by
|
||||
func ComputeSharedSecret(pkh, skh string) (sharedSecret []byte, err error) {
|
||||
var skb, pkb []byte
|
||||
if skb, err = hex.Dec(skh); chk.E(err) {
|
||||
return
|
||||
}
|
||||
@@ -38,9 +39,9 @@ func ComputeSharedSecret(pkh, skh st) (sharedSecret by, err er) {
|
||||
// Returns: base64(encrypted_bytes) + "?iv=" + base64(initialization_vector).
|
||||
//
|
||||
// Deprecated: upgrade to using Decrypt with the NIP-44 algorithm.
|
||||
func EncryptNip4(msg st, key by) (ct by, err er) {
|
||||
func EncryptNip4(msg string, key []byte) (ct []byte, err error) {
|
||||
// block size is 16 bytes
|
||||
iv := make(by, 16)
|
||||
iv := make([]byte, 16)
|
||||
if _, err = frand.Read(iv); chk.E(err) {
|
||||
err = errorf.E("error creating initialization vector: %w", err)
|
||||
return
|
||||
@@ -52,18 +53,18 @@ func EncryptNip4(msg st, key by) (ct by, err er) {
|
||||
return
|
||||
}
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
plaintext := by(msg)
|
||||
plaintext := []byte(msg)
|
||||
// add padding
|
||||
base := len(plaintext)
|
||||
// this will be a number between 1 and 16 (inclusive), never 0
|
||||
bs := block.BlockSize()
|
||||
padding := bs - base%bs
|
||||
// encode the padding in all the padding bytes themselves
|
||||
padText := bytes.Repeat(by{byte(padding)}, padding)
|
||||
padText := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||
paddedMsgBytes := append(plaintext, padText...)
|
||||
ciphertext := make(by, len(paddedMsgBytes))
|
||||
ciphertext := make([]byte, len(paddedMsgBytes))
|
||||
mode.CryptBlocks(ciphertext, paddedMsgBytes)
|
||||
return by(base64.StdEncoding.EncodeToString(ciphertext) + "?iv=" +
|
||||
return []byte(base64.StdEncoding.EncodeToString(ciphertext) + "?iv=" +
|
||||
base64.StdEncoding.EncodeToString(iv)), nil
|
||||
}
|
||||
|
||||
@@ -71,18 +72,18 @@ func EncryptNip4(msg st, key by) (ct by, err er) {
|
||||
// EncryptNip4(message, key).
|
||||
//
|
||||
// Deprecated: upgrade to using Decrypt with the NIP-44 algorithm.
|
||||
func DecryptNip4(content st, key by) (msg by, err er) {
|
||||
func DecryptNip4(content string, key []byte) (msg []byte, err error) {
|
||||
parts := strings.Split(content, "?iv=")
|
||||
if len(parts) < 2 {
|
||||
return nil, errorf.E(
|
||||
"error parsing encrypted message: no initialization vector")
|
||||
}
|
||||
var ciphertext by
|
||||
var ciphertext []byte
|
||||
if ciphertext, err = base64.StdEncoding.DecodeString(parts[0]); chk.E(err) {
|
||||
err = errorf.E("error decoding ciphertext from base64: %w", err)
|
||||
return
|
||||
}
|
||||
var iv by
|
||||
var iv []byte
|
||||
if iv, err = base64.StdEncoding.DecodeString(parts[1]); chk.E(err) {
|
||||
err = errorf.E("error decoding iv from base64: %w", err)
|
||||
return
|
||||
@@ -93,7 +94,7 @@ func DecryptNip4(content st, key by) (msg by, err er) {
|
||||
return
|
||||
}
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
msg = make(by, len(ciphertext))
|
||||
msg = make([]byte, len(ciphertext))
|
||||
mode.CryptBlocks(msg, ciphertext)
|
||||
// remove padding
|
||||
var (
|
||||
@@ -101,7 +102,7 @@ func DecryptNip4(content st, key by) (msg by, err er) {
|
||||
)
|
||||
if plaintextLen > 0 {
|
||||
// the padding amount is encoded in the padding bytes themselves
|
||||
padding := no(msg[plaintextLen-1])
|
||||
padding := int(msg[plaintextLen-1])
|
||||
if padding > plaintextLen {
|
||||
err = errorf.E("invalid padding amount: %d", padding)
|
||||
return
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"golang.org/x/crypto/chacha20"
|
||||
"golang.org/x/crypto/hkdf"
|
||||
|
||||
"realy.lol/sha256"
|
||||
)
|
||||
|
||||
@@ -21,14 +22,14 @@ const (
|
||||
)
|
||||
|
||||
type Opts struct {
|
||||
err er
|
||||
nonce by
|
||||
err error
|
||||
nonce []byte
|
||||
}
|
||||
|
||||
// Deprecated: use WithCustomNonce instead of WithCustomSalt, so the naming is less confusing
|
||||
var WithCustomSalt = WithCustomNonce
|
||||
|
||||
func WithCustomNonce(salt by) func(opts *Opts) {
|
||||
func WithCustomNonce(salt []byte) func(opts *Opts) {
|
||||
return func(opts *Opts) {
|
||||
if len(salt) != 32 {
|
||||
opts.err = errorf.E("salt must be 32 bytes, got %d", len(salt))
|
||||
@@ -37,9 +38,9 @@ func WithCustomNonce(salt by) func(opts *Opts) {
|
||||
}
|
||||
}
|
||||
|
||||
func Encrypt(plaintext st, conversationKey by,
|
||||
applyOptions ...func(opts *Opts)) (cipherString st,
|
||||
err er) {
|
||||
func Encrypt(plaintext string, conversationKey []byte,
|
||||
applyOptions ...func(opts *Opts)) (cipherString string,
|
||||
err error) {
|
||||
var o Opts
|
||||
for _, apply := range applyOptions {
|
||||
apply(&o)
|
||||
@@ -49,34 +50,34 @@ func Encrypt(plaintext st, conversationKey by,
|
||||
return
|
||||
}
|
||||
if o.nonce == nil {
|
||||
o.nonce = make(by, 32)
|
||||
o.nonce = make([]byte, 32)
|
||||
if _, err = rand.Read(o.nonce); chk.E(err) {
|
||||
return
|
||||
}
|
||||
}
|
||||
var enc, cc20nonce, auth by
|
||||
var enc, cc20nonce, auth []byte
|
||||
if enc, cc20nonce, auth, err = getKeys(conversationKey, o.nonce); chk.E(err) {
|
||||
return
|
||||
}
|
||||
plain := by(plaintext)
|
||||
plain := []byte(plaintext)
|
||||
size := len(plain)
|
||||
if size < MinPlaintextSize || size > MaxPlaintextSize {
|
||||
err = errorf.E("plaintext should be between 1b and 64kB")
|
||||
return
|
||||
}
|
||||
padding := calcPadding(size)
|
||||
padded := make(by, 2+padding)
|
||||
padded := make([]byte, 2+padding)
|
||||
binary.BigEndian.PutUint16(padded, uint16(size))
|
||||
copy(padded[2:], plain)
|
||||
var cipher by
|
||||
var cipher []byte
|
||||
if cipher, err = encrypt(enc, cc20nonce, padded); chk.E(err) {
|
||||
return
|
||||
}
|
||||
var mac by
|
||||
var mac []byte
|
||||
if mac, err = sha256Hmac(auth, cipher, o.nonce); chk.E(err) {
|
||||
return
|
||||
}
|
||||
ct := make(by, 0, 1+32+len(cipher)+32)
|
||||
ct := make([]byte, 0, 1+32+len(cipher)+32)
|
||||
ct = append(ct, version)
|
||||
ct = append(ct, o.nonce...)
|
||||
ct = append(ct, cipher...)
|
||||
@@ -85,7 +86,7 @@ func Encrypt(plaintext st, conversationKey by,
|
||||
return
|
||||
}
|
||||
|
||||
func Decrypt(b64ciphertextWrapped st, conversationKey by) (plaintext st, err er) {
|
||||
func Decrypt(b64ciphertextWrapped string, conversationKey []byte) (plaintext string, err error) {
|
||||
cLen := len(b64ciphertextWrapped)
|
||||
if cLen < 132 || cLen > 87472 {
|
||||
err = errorf.E("invalid payload length: %d", cLen)
|
||||
@@ -95,7 +96,7 @@ func Decrypt(b64ciphertextWrapped st, conversationKey by) (plaintext st, err er)
|
||||
err = errorf.E("unknown version")
|
||||
return
|
||||
}
|
||||
var decoded by
|
||||
var decoded []byte
|
||||
if decoded, err = base64.StdEncoding.DecodeString(b64ciphertextWrapped); chk.E(err) {
|
||||
return
|
||||
}
|
||||
@@ -109,11 +110,11 @@ func Decrypt(b64ciphertextWrapped st, conversationKey by) (plaintext st, err er)
|
||||
return
|
||||
}
|
||||
nonce, ciphertext, givenMac := decoded[1:33], decoded[33:dLen-32], decoded[dLen-32:]
|
||||
var enc, cc20nonce, auth by
|
||||
var enc, cc20nonce, auth []byte
|
||||
if enc, cc20nonce, auth, err = getKeys(conversationKey, nonce); chk.E(err) {
|
||||
return
|
||||
}
|
||||
var expectedMac by
|
||||
var expectedMac []byte
|
||||
if expectedMac, err = sha256Hmac(auth, ciphertext, nonce); chk.E(err) {
|
||||
return
|
||||
}
|
||||
@@ -121,51 +122,51 @@ func Decrypt(b64ciphertextWrapped st, conversationKey by) (plaintext st, err er)
|
||||
err = errorf.E("invalid hmac")
|
||||
return
|
||||
}
|
||||
var padded by
|
||||
var padded []byte
|
||||
if padded, err = encrypt(enc, cc20nonce, ciphertext); chk.E(err) {
|
||||
return
|
||||
}
|
||||
unpaddedLen := binary.BigEndian.Uint16(padded[0:2])
|
||||
if unpaddedLen < uint16(MinPlaintextSize) || unpaddedLen > uint16(MaxPlaintextSize) ||
|
||||
len(padded) != 2+calcPadding(no(unpaddedLen)) {
|
||||
len(padded) != 2+calcPadding(int(unpaddedLen)) {
|
||||
err = errorf.E("invalid padding")
|
||||
return
|
||||
}
|
||||
unpadded := padded[2:][:unpaddedLen]
|
||||
if len(unpadded) == 0 || len(unpadded) != no(unpaddedLen) {
|
||||
if len(unpadded) == 0 || len(unpadded) != int(unpaddedLen) {
|
||||
err = errorf.E("invalid padding")
|
||||
return
|
||||
}
|
||||
plaintext = st(unpadded)
|
||||
plaintext = string(unpadded)
|
||||
return
|
||||
}
|
||||
|
||||
func GenerateConversationKey(pkh, skh st) (ck by, err er) {
|
||||
func GenerateConversationKey(pkh, skh string) (ck []byte, err error) {
|
||||
if skh >= "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141" ||
|
||||
skh == "0000000000000000000000000000000000000000000000000000000000000000" {
|
||||
err = errorf.E("invalid private key: x coordinate %s is not on the secp256k1 curve",
|
||||
skh)
|
||||
return
|
||||
}
|
||||
var shared by
|
||||
var shared []byte
|
||||
if shared, err = ComputeSharedSecret(pkh, skh); chk.E(err) {
|
||||
return
|
||||
}
|
||||
ck = hkdf.Extract(sha256.New, shared, by("nip44-v2"))
|
||||
ck = hkdf.Extract(sha256.New, shared, []byte("nip44-v2"))
|
||||
return
|
||||
}
|
||||
|
||||
func encrypt(key, nonce, message by) (dst by, err er) {
|
||||
func encrypt(key, nonce, message []byte) (dst []byte, err error) {
|
||||
var cipher *chacha20.Cipher
|
||||
if cipher, err = chacha20.NewUnauthenticatedCipher(key, nonce); chk.E(err) {
|
||||
return
|
||||
}
|
||||
dst = make(by, len(message))
|
||||
dst = make([]byte, len(message))
|
||||
cipher.XORKeyStream(dst, message)
|
||||
return
|
||||
}
|
||||
|
||||
func sha256Hmac(key, ciphertext, nonce by) (h by, err er) {
|
||||
func sha256Hmac(key, ciphertext, nonce []byte) (h []byte, err error) {
|
||||
if len(nonce) != sha256.Size {
|
||||
err = errorf.E("nonce aad must be 32 bytes")
|
||||
return
|
||||
@@ -177,7 +178,7 @@ func sha256Hmac(key, ciphertext, nonce by) (h by, err er) {
|
||||
return
|
||||
}
|
||||
|
||||
func getKeys(conversationKey, nonce by) (enc, cc20nonce, auth by, err er) {
|
||||
func getKeys(conversationKey, nonce []byte) (enc, cc20nonce, auth []byte, err error) {
|
||||
if len(conversationKey) != 32 {
|
||||
err = errorf.E("conversation key must be 32 bytes")
|
||||
return
|
||||
@@ -187,27 +188,27 @@ func getKeys(conversationKey, nonce by) (enc, cc20nonce, auth by, err er) {
|
||||
return
|
||||
}
|
||||
r := hkdf.Expand(sha256.New, conversationKey, nonce)
|
||||
enc = make(by, 32)
|
||||
enc = make([]byte, 32)
|
||||
if _, err = io.ReadFull(r, enc); chk.E(err) {
|
||||
return
|
||||
}
|
||||
cc20nonce = make(by, 12)
|
||||
cc20nonce = make([]byte, 12)
|
||||
if _, err = io.ReadFull(r, cc20nonce); chk.E(err) {
|
||||
return
|
||||
}
|
||||
auth = make(by, 32)
|
||||
auth = make([]byte, 32)
|
||||
if _, err = io.ReadFull(r, auth); chk.E(err) {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func calcPadding(sLen no) (l no) {
|
||||
func calcPadding(sLen int) (l int) {
|
||||
if sLen <= 32 {
|
||||
return 32
|
||||
}
|
||||
nextPower := 1 << no(math.Floor(math.Log2(float64(sLen-1)))+1)
|
||||
chunk := no(math.Max(32, float64(nextPower/8)))
|
||||
l = chunk * no(math.Floor(float64((sLen-1)/chunk))+1)
|
||||
nextPower := 1 << int(math.Floor(math.Log2(float64(sLen-1)))+1)
|
||||
chunk := int(math.Max(32, float64(nextPower/8)))
|
||||
l = chunk * int(math.Floor(float64((sLen-1)/chunk))+1)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -14,12 +14,12 @@ import (
|
||||
"realy.lol/sha256"
|
||||
)
|
||||
|
||||
func assertCryptPriv(t *testing.T, sk1, sk2, conversationKey, salt, plaintext, expected st) {
|
||||
func assertCryptPriv(t *testing.T, sk1, sk2, conversationKey, salt, plaintext, expected string) {
|
||||
var (
|
||||
k1, s by
|
||||
actual, decrypted st
|
||||
ok bo
|
||||
err er
|
||||
k1, s []byte
|
||||
actual, decrypted string
|
||||
ok bool
|
||||
err error
|
||||
)
|
||||
k1, err = hex.Dec(conversationKey)
|
||||
if ok = assert.NoErrorf(t, err, "hex decode failed for conversation key: %v", err); !ok {
|
||||
@@ -46,11 +46,11 @@ func assertCryptPriv(t *testing.T, sk1, sk2, conversationKey, salt, plaintext, e
|
||||
assert.Equal(t, decrypted, plaintext, "wrong decryption")
|
||||
}
|
||||
|
||||
func assertDecryptFail(t *testing.T, conversationKey, plaintext, ciphertext, msg st) {
|
||||
func assertDecryptFail(t *testing.T, conversationKey, plaintext, ciphertext, msg string) {
|
||||
var (
|
||||
k1 by
|
||||
ok bo
|
||||
err er
|
||||
k1 []byte
|
||||
ok bool
|
||||
err error
|
||||
)
|
||||
k1, err = hex.Dec(conversationKey)
|
||||
if ok = assert.NoErrorf(t, err, "hex decode failed for conversation key: %v", err); !ok {
|
||||
@@ -60,17 +60,17 @@ func assertDecryptFail(t *testing.T, conversationKey, plaintext, ciphertext, msg
|
||||
assert.ErrorContains(t, err, msg)
|
||||
}
|
||||
|
||||
func assertConversationKeyFail(t *testing.T, priv st, pub st, msg st) {
|
||||
func assertConversationKeyFail(t *testing.T, priv string, pub string, msg string) {
|
||||
_, err := GenerateConversationKey(pub, priv)
|
||||
assert.ErrorContains(t, err, msg)
|
||||
}
|
||||
|
||||
func assertConversationKeyGeneration(t *testing.T, priv, pub, conversationKey st) bo {
|
||||
func assertConversationKeyGeneration(t *testing.T, priv, pub, conversationKey string) bool {
|
||||
var (
|
||||
actualConversationKey,
|
||||
expectedConversationKey by
|
||||
ok bo
|
||||
err er
|
||||
expectedConversationKey []byte
|
||||
ok bool
|
||||
err error
|
||||
)
|
||||
expectedConversationKey, err = hex.Dec(conversationKey)
|
||||
if ok = assert.NoErrorf(t, err, "hex decode failed for conversation key: %v", err); !ok {
|
||||
@@ -87,7 +87,7 @@ func assertConversationKeyGeneration(t *testing.T, priv, pub, conversationKey st
|
||||
return true
|
||||
}
|
||||
|
||||
func assertConversationKeyGenerationSec(t *testing.T, sk1, sk2, conversationKey st) bo {
|
||||
func assertConversationKeyGenerationSec(t *testing.T, sk1, sk2, conversationKey string) bool {
|
||||
pub2, err := keys.GetPublicKeyHex(sk2)
|
||||
if ok := assert.NoErrorf(t, err, "failed to derive pubkey from sk2: %v", err); !ok {
|
||||
return false
|
||||
@@ -95,17 +95,17 @@ func assertConversationKeyGenerationSec(t *testing.T, sk1, sk2, conversationKey
|
||||
return assertConversationKeyGeneration(t, sk1, pub2, conversationKey)
|
||||
}
|
||||
|
||||
func assertConversationKeyGenerationPub(t *testing.T, sk, pub, conversationKey st) bo {
|
||||
func assertConversationKeyGenerationPub(t *testing.T, sk, pub, conversationKey string) bool {
|
||||
return assertConversationKeyGeneration(t, sk, pub, conversationKey)
|
||||
}
|
||||
|
||||
func assertMessageKeyGeneration(t *testing.T,
|
||||
conversationKey, salt, chachaKey, chachaSalt, hmacKey st) bo {
|
||||
conversationKey, salt, chachaKey, chachaSalt, hmacKey string) bool {
|
||||
var (
|
||||
convKey, convSalt, actualChaChaKey, expectedChaChaKey, actualChaChaNonce,
|
||||
expectedChaChaNonce, actualHmacKey, expectedHmacKey by
|
||||
ok bo
|
||||
err er
|
||||
expectedChaChaNonce, actualHmacKey, expectedHmacKey []byte
|
||||
ok bool
|
||||
err error
|
||||
)
|
||||
convKey, err = hex.Dec(conversationKey)
|
||||
if ok = assert.NoErrorf(t, err, "hex decode failed for convKey: %v", err); !ok {
|
||||
@@ -144,14 +144,14 @@ func assertMessageKeyGeneration(t *testing.T,
|
||||
return true
|
||||
}
|
||||
|
||||
func assertCryptLong(t *testing.T, conversationKey, salt, pattern st, repeat int,
|
||||
plaintextSha256, payloadSha256 st) {
|
||||
func assertCryptLong(t *testing.T, conversationKey, salt, pattern string, repeat int,
|
||||
plaintextSha256, payloadSha256 string) {
|
||||
var (
|
||||
convKey, convSalt by
|
||||
plaintext, actualPlaintextSha256, actualPayload, actualPayloadSha256 st
|
||||
convKey, convSalt []byte
|
||||
plaintext, actualPlaintextSha256, actualPayload, actualPayloadSha256 string
|
||||
h hash.Hash
|
||||
ok bo
|
||||
err er
|
||||
ok bool
|
||||
err error
|
||||
)
|
||||
convKey, err = hex.Dec(conversationKey)
|
||||
if ok = assert.NoErrorf(t, err, "hex decode failed for convKey: %v", err); !ok {
|
||||
@@ -166,7 +166,7 @@ func assertCryptLong(t *testing.T, conversationKey, salt, pattern st, repeat int
|
||||
plaintext += pattern
|
||||
}
|
||||
h = sha256.New()
|
||||
h.Write(by(plaintext))
|
||||
h.Write([]byte(plaintext))
|
||||
actualPlaintextSha256 = hex.Enc(h.Sum(nil))
|
||||
if ok = assert.Equalf(t, plaintextSha256, actualPlaintextSha256,
|
||||
"invalid plaintext sha256 hash: %v", err); !ok {
|
||||
@@ -177,7 +177,7 @@ func assertCryptLong(t *testing.T, conversationKey, salt, pattern st, repeat int
|
||||
return
|
||||
}
|
||||
h.Reset()
|
||||
h.Write(by(actualPayload))
|
||||
h.Write([]byte(actualPayload))
|
||||
actualPayloadSha256 = hex.Enc(h.Sum(nil))
|
||||
if ok = assert.Equalf(t, payloadSha256, actualPayloadSha256,
|
||||
"invalid payload sha256 hash: %v", err); !ok {
|
||||
@@ -1142,10 +1142,10 @@ func TestMessageKeyGeneration033(t *testing.T) {
|
||||
func TestMaxLength(t *testing.T) {
|
||||
sk1 := keys.GeneratePrivateKey()
|
||||
sk2 := keys.GeneratePrivateKey()
|
||||
pub2, _ := keys.GetPublicKeyHex(st(sk2))
|
||||
salt := make(by, 32)
|
||||
pub2, _ := keys.GetPublicKeyHex(string(sk2))
|
||||
salt := make([]byte, 32)
|
||||
rand.Read(salt)
|
||||
conversationKey, _ := GenerateConversationKey(pub2, st(sk1))
|
||||
conversationKey, _ := GenerateConversationKey(pub2, string(sk1))
|
||||
plaintext := strings.Repeat("a", MaxPlaintextSize)
|
||||
encrypted, err := Encrypt(plaintext, conversationKey, WithCustomNonce(salt))
|
||||
if chk.E(err) {
|
||||
@@ -1153,7 +1153,7 @@ func TestMaxLength(t *testing.T) {
|
||||
}
|
||||
|
||||
assertCryptPub(t,
|
||||
st(sk1),
|
||||
string(sk1),
|
||||
pub2,
|
||||
fmt.Sprintf("%x", conversationKey),
|
||||
fmt.Sprintf("%x", salt),
|
||||
@@ -1162,12 +1162,12 @@ func TestMaxLength(t *testing.T) {
|
||||
)
|
||||
}
|
||||
|
||||
func assertCryptPub(t *testing.T, sk1, pub2, conversationKey, salt, plaintext, expected st) {
|
||||
func assertCryptPub(t *testing.T, sk1, pub2, conversationKey, salt, plaintext, expected string) {
|
||||
var (
|
||||
k1, s by
|
||||
actual, decrypted st
|
||||
ok bo
|
||||
err er
|
||||
k1, s []byte
|
||||
actual, decrypted string
|
||||
ok bool
|
||||
err error
|
||||
)
|
||||
k1, err = hex.Dec(conversationKey)
|
||||
if ok = assert.NoErrorf(t, err, "hex decode failed for conversation key: %v", err); !ok {
|
||||
|
||||
@@ -1,22 +1,9 @@
|
||||
package encryption
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"realy.lol/context"
|
||||
"realy.lol/lol"
|
||||
)
|
||||
|
||||
type (
|
||||
bo = bool
|
||||
by = []byte
|
||||
st = string
|
||||
er = error
|
||||
no = int
|
||||
cx = context.T
|
||||
)
|
||||
|
||||
var (
|
||||
log, chk, errorf = lol.Main.Log, lol.Main.Check, lol.Main.Errorf
|
||||
equals = bytes.Equal
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user