Compare commits

...

2 Commits

Author SHA1 Message Date
Evan Su 90ec24c941
Add web interface 2023-08-05 18:12:06 -04:00
Evan Su cf09de407a
Add web interface 2023-08-05 17:16:38 -04:00
5 changed files with 420 additions and 0 deletions

View File

@ -24,6 +24,9 @@ Picocrypt for macOS is very simple as well. Download Picocrypt <a href="https://
## Linux
To use Picocrypt on Linux, you can download the AppImage <a href="https://github.com/HACKERALERT/Picocrypt/releases/download/1.33/Picocrypt.AppImage">here</a>. While this AppImage should work on most systems, Linux is a mess when it comes to cross-distro and cross-release compatibility, so if the AppImage doesn't work, you can try the <a href="https://snapcraft.io/picocrypt">Snap</a>, run Picocrypt through Wine, or compile from source using the instructions in the `src/` directory.
## Web
A web interface for Picocrypt is available <a href="https://picocrypt.pages.dev/">here</a>, allowing you to use a lite version of Picocrypt on any device. Keep in mind that its functionality is very limited and you won't be able to use any advanced features. It is also quite slow compared to the native app.
## CLI
A command-line interface is available for Picocrypt <a href="/cli">here</a>. Keep in mind that the functionality is extremely limited and is not meant to replace the standard GUI app. Rather, it's best suited for environments where the GUI won't run or you need the ability to automate encryption workflows.

10
web/go.mod Normal file
View File

@ -0,0 +1,10 @@
module Picocrypt
go 1.17
require (
github.com/HACKERALERT/crypto v0.0.0-20220905152506-aa0dd62d8f67
github.com/HACKERALERT/infectious v0.0.0-20220905152109-2c37b99f37ff
)
require github.com/HACKERALERT/sys v0.0.0-20220905150735-46e319fb60c9 // indirect

6
web/go.sum Normal file
View File

@ -0,0 +1,6 @@
github.com/HACKERALERT/crypto v0.0.0-20220905152506-aa0dd62d8f67 h1:4WfPIopYjvBjyDg0IET7mEj32kkihLmvFgwCOmldqK8=
github.com/HACKERALERT/crypto v0.0.0-20220905152506-aa0dd62d8f67/go.mod h1:qiHCxMDsCxX4QhXd3kDYWiNOR/DZQZ7nYO/f2OgWst0=
github.com/HACKERALERT/infectious v0.0.0-20220905152109-2c37b99f37ff h1:ertDhqhixxQJJPJIpn4wmSVs2fQ3tlSDNuiZ7jHCvEs=
github.com/HACKERALERT/infectious v0.0.0-20220905152109-2c37b99f37ff/go.mod h1:GwBVHbiXRUUciGfKWwm4GCL8FvMZBLHrQq23UXW/CU8=
github.com/HACKERALERT/sys v0.0.0-20220905150735-46e319fb60c9 h1:raqLJhvqDGk9L4dnJnO0tTV5Lyba2jhQcIHEle+o1dM=
github.com/HACKERALERT/sys v0.0.0-20220905150735-46e319fb60c9/go.mod h1:I4esFWbCYc37CXVb+3qJHJiU43NGkLf66kNV/NDnXcU=

199
web/index.go Normal file
View File

@ -0,0 +1,199 @@
package main
/*
Picocrypt v1.33 (WebAssembly Version)
Copyright (c) Evan Su
Released under a GNU GPL v3 License
https://github.com/HACKERALERT/Picocrypt
~ In cryptography we trust ~
*/
import (
"bytes"
"crypto/rand"
"strconv"
"strings"
"syscall/js"
"github.com/HACKERALERT/crypto/argon2"
"github.com/HACKERALERT/crypto/blake2b"
"github.com/HACKERALERT/crypto/chacha20"
"github.com/HACKERALERT/crypto/hkdf"
"github.com/HACKERALERT/crypto/sha3"
"github.com/HACKERALERT/infectious"
)
var MiB = 1 << 20
var GiB = 1 << 30
var rs5, _ = infectious.NewFEC(5, 15)
var rs16, _ = infectious.NewFEC(16, 48)
var rs24, _ = infectious.NewFEC(24, 72)
var rs32, _ = infectious.NewFEC(32, 96)
var rs64, _ = infectious.NewFEC(64, 192)
var password string
func work(din []byte, mode string) []byte {
var salt []byte
var hkdfSalt []byte
var nonce []byte
var keyHash []byte
var keyHashRef []byte
var authTag []byte
var dout []byte
if mode == "encrypt" {
salt = make([]byte, 16)
hkdfSalt = make([]byte, 32)
nonce = make([]byte, 24)
rand.Read(salt)
rand.Read(hkdfSalt)
rand.Read(nonce)
dout = append(dout, rsEncode(rs5, []byte("v1.33"))...)
dout = append(dout, rsEncode(rs5, []byte("00000"))...)
dout = append(dout, rsEncode(rs5, make([]byte, 5))...)
dout = append(dout, rsEncode(rs16, salt)...)
dout = append(dout, rsEncode(rs32, hkdfSalt)...)
dout = append(dout, rsEncode(rs16, make([]byte, 16))...)
dout = append(dout, rsEncode(rs24, nonce)...)
dout = append(dout, make([]byte, 480)...)
} else {
errs, tmp := make([]error, 7), make([]byte, 15)
tmp, din = din[15:30], din[30:]
tmp, errs[0] = rsDecode(rs5, tmp)
c, _ := strconv.Atoi(string(tmp))
tmp, din = din[c*3:c*3+15], din[c*3+15:]
tmp, errs[1] = rsDecode(rs5, tmp)
if tmp[0]+tmp[1]+tmp[3] > 0 {
return []byte{1}
}
salt, din = din[:48], din[48:]
salt, errs[2] = rsDecode(rs16, salt)
hkdfSalt, din = din[:96], din[96:]
hkdfSalt, errs[3] = rsDecode(rs32, hkdfSalt)
nonce, din = din[48:120], din[120:]
nonce, errs[4] = rsDecode(rs24, nonce)
keyHashRef, din = din[:192], din[192:]
keyHashRef, errs[5] = rsDecode(rs64, keyHashRef)
authTag, din = din[96:288], din[288:]
authTag, errs[6] = rsDecode(rs64, authTag)
for _, err := range errs {
if err != nil {
return []byte{2}
}
}
}
key := argon2.IDKey([]byte(password), salt, 4, 1<<20, 4, 32)
tmp := sha3.New512()
tmp.Write(key)
keyHash = tmp.Sum(nil)
if mode == "decrypt" && !bytes.Equal(keyHash, keyHashRef) {
return []byte{3}
}
counter := 0
chacha, _ := chacha20.NewUnauthenticatedCipher(key, nonce)
subkey := make([]byte, 32)
hkdf := hkdf.New(sha3.New256, key, hkdfSalt, nil)
hkdf.Read(subkey)
mac, _ := blake2b.New512(subkey)
hkdf.Read(make([]byte, 32))
for {
var src []byte
if len(din) == 0 {
break
} else if len(din) < MiB {
src, din = din, nil
} else {
src, din = din[:MiB], din[MiB:]
}
dst := make([]byte, len(src))
if mode == "encrypt" {
chacha.XORKeyStream(dst, src)
mac.Write(dst)
} else {
mac.Write(src)
chacha.XORKeyStream(dst, src)
}
dout = append(dout, dst...)
counter += MiB
if counter >= 60*GiB {
nonce = make([]byte, 24)
hkdf.Read(nonce)
chacha, _ = chacha20.NewUnauthenticatedCipher(key, nonce)
hkdf.Read(make([]byte, 16))
counter = 0
}
}
if mode == "encrypt" {
buff := rsEncode(rs64, keyHash)
buff = append(buff, rsEncode(rs32, make([]byte, 32))...)
buff = append(buff, rsEncode(rs64, mac.Sum(nil))...)
for i, v := range buff {
dout[309+i] = v
}
} else {
if !bytes.Equal(mac.Sum(nil), authTag) {
return []byte{4}
}
}
return append([]byte{0}, dout...)
}
func rsEncode(rs *infectious.FEC, data []byte) []byte {
res := make([]byte, rs.Total())
rs.Encode(data, func(s infectious.Share) {
res[s.Number] = s.Data[0]
})
return res
}
func rsDecode(rs *infectious.FEC, data []byte) ([]byte, error) {
tmp := make([]infectious.Share, rs.Total())
for i := 0; i < rs.Total(); i++ {
tmp[i].Number = i
tmp[i].Data = []byte{data[i]}
}
res, err := rs.Decode(nil, tmp)
if err != nil {
return data[:rs.Total()/3], err
}
return res, nil
}
func main() {
quit := make(chan struct{}, 0)
document := js.Global().Get("document")
input := document.Call("getElementById", "fin")
button := document.Call("getElementById", "work")
callback := js.FuncOf(func(v js.Value, x []js.Value) any {
var dout []byte
data := js.Global().Get("Uint8Array").New(x[0])
din := make([]byte, data.Get("length").Int())
js.CopyBytesToGo(din, data)
password = document.Call("getElementById", "password").Get("value").String()
filename := input.Get("files").Call("item", 0).Get("name").String()
if strings.HasSuffix(filename, ".pcv") {
dout = work(din, "decrypt")
} else {
dout = work(din, "encrypt")
}
arr := js.Global().Get("Uint8Array").New(len(dout))
js.CopyBytesToJS(arr, dout)
js.Global().Call("download", arr)
return nil
})
button.Set("onclick", js.FuncOf(func(v js.Value, x []js.Value) any {
input.Get("files").Call("item", 0).Call("arrayBuffer").Call("then", callback)
return nil
}))
<-quit
}

202
web/index.html Normal file

File diff suppressed because one or more lines are too long