Update version to 1.4.0, encryption options in config
This commit is contained in:
parent
dec70f1466
commit
0cc42f57e6
19
README.md
19
README.md
|
@ -1,16 +1,11 @@
|
|||
![](https://i.imgur.com/AHHWH3z.png)
|
||||
|
||||
# Tytanium
|
||||
## Tytanium
|
||||
|
||||
A durable and secure private file host solution. Intended for personal or small group use.
|
||||
|
||||
## Features
|
||||
Tytanium is a private file host program, meant for a single user or a small group. Here are the main highlights:
|
||||
|
||||
- SHA-512 file encryption at rest, with an encryption key unique to each file
|
||||
- Tune the server to exactly how you want with extensive customization options
|
||||
- Built with [fasthttp](https://github.com/vayala/fasthttp) for optimal performance instead of the native http module
|
||||
- File whitelist/blacklist type checks done via file headers rather than extensions
|
||||
- Sanitize file type from rendering in HTML/other types to mitigate phishing attacks (Change their Content-Type to text/plain)
|
||||
- Option to return a zero-width file IDs in a URL after upload - paste invisible but functional links!
|
||||
- Works well with image capture suites, such as ShareX/MagicCap
|
||||
- Good on system resources (<1MiB memory usage when idle)
|
||||
- Limit how many requests/second to certain paths to prevent DoS attacks or an overloaded server
|
||||
|
@ -20,15 +15,13 @@ A durable and secure private file host solution. Intended for personal or small
|
|||
|
||||
1. Download the binary in the Releases tab, or build the code from source.
|
||||
2. Rename `example.yml` to `config.yml` and set the values you want, or create a `config.yml` from scratch.
|
||||
3. Start the binary with your method of choice.
|
||||
4. Done!
|
||||
3. Mark the binary as executable (this can be done with `chmod`).
|
||||
|
||||
### How to Use
|
||||
### How to Upload
|
||||
|
||||
1. Create a POST request to `/upload` with a file in the field "file". Put the key in the `Authorization` header.
|
||||
2. Set `?omitdomain=1`, if you don't want the host's original domain appended before the file name in the response. For example: `a.png` instead of `https://a.com/a.png`. This is useful if you have vanity/proxy domains you want to use.
|
||||
3. Add `?zerowidth=1` and set it to `1` to make your image URLs appear "zero-width". If you don't get what that means, try it, and see what happens.
|
||||
4. The server will respond with a link to the file (or just the file name if you set `?omitdomain=1`). It will be just text so no need to parse any JSON.
|
||||
3. The server will respond with JSON with fields `uri` and `encryption_key`. `uri` will be just the file name if `?omitdomain=1` was specified.
|
||||
|
||||
### Optional stuff
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ type Configuration struct {
|
|||
StatsCollectionInterval int
|
||||
Logging loggingConfig
|
||||
Encryption encryptionConfig
|
||||
Domain string
|
||||
}
|
||||
|
||||
type encryptionConfig struct {
|
||||
|
|
|
@ -108,3 +108,19 @@ Logging: # Configure logging behavior.
|
|||
|
||||
# If logging is enabled, where should logs be written to? (Default is "log.txt" file in the project dir)
|
||||
LogFile:
|
||||
|
||||
Encryption: # Configure encryption behavior.
|
||||
# The length of the encryption key that is used in the query string (enc_key) when decoding files.
|
||||
# Try not to make it too long or URLs will be abnormally long.
|
||||
# By default, the length is 12.
|
||||
EncryptionKeyLength:
|
||||
|
||||
# The string which helps in creating the encryption key for files.
|
||||
# You don't have to keep it private, and it can be any string.
|
||||
# Keep in mind that if you change this, files previously encrypted using this nonce will be impossible to decrypt.
|
||||
Nonce:
|
||||
|
||||
# The URL from which this server will be accessible from, for example, https://example.com.
|
||||
# If you have multiple proxy domains, pick one of them to use here;
|
||||
# it doesn't matter as long as it connects to the server.
|
||||
Domain:
|
|
@ -23,7 +23,7 @@ const (
|
|||
|
||||
const (
|
||||
RateLimitBandwidthDownload = "bw_dn_"
|
||||
RateLimitBandwidthUpload = "bw_up_"
|
||||
RateLimitBandwidthUpload = "bw_up_"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
4
go.mod
4
go.mod
|
@ -1,4 +1,4 @@
|
|||
module github.com/vysiondev/tytanium
|
||||
module tytanium
|
||||
|
||||
go 1.17
|
||||
|
||||
|
@ -17,6 +17,7 @@ require (
|
|||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/klauspost/compress v1.15.0 // indirect
|
||||
github.com/magiconair/properties v1.8.5 // indirect
|
||||
github.com/minio/sio v0.3.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
||||
github.com/pelletier/go-toml v1.9.3 // indirect
|
||||
github.com/spf13/afero v1.6.0 // indirect
|
||||
|
@ -25,6 +26,7 @@ require (
|
|||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/subosito/gotenv v1.2.0 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
|
|
7
go.sum
7
go.sum
|
@ -39,6 +39,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
|
|||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/Xeoncross/go-aesctr-with-hmac v0.0.0-20200623134604-12b17a7ff502 h1:L8IbaI/W6h5Cwgh0n4zGeZpVK78r/jBf9ASurHo9+/o=
|
||||
github.com/Xeoncross/go-aesctr-with-hmac v0.0.0-20200623134604-12b17a7ff502/go.mod h1:pmnBM9bxWSiHvC/gSWunUIyDvGn33EkP2CUjxFKtTTM=
|
||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
|
@ -195,6 +197,8 @@ github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK
|
|||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/minio/sio v0.3.0 h1:syEFBewzOMOYVzSTFpp1MqpSZk8rUNbz8VIIc+PNzus=
|
||||
github.com/minio/sio v0.3.0/go.mod h1:8b0yPp2avGThviy/+OCJBI6OMpvxoUuiLvE6F1lebhw=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
|
@ -284,10 +288,12 @@ go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
|||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
|
@ -441,6 +447,7 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs=
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
72
utils/zws.go
72
utils/zws.go
|
@ -1,72 +0,0 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// hey yeah if it works and its stupid it aint stupid
|
||||
const characterIndex = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789."
|
||||
|
||||
var (
|
||||
characterReference = []string{
|
||||
"\U000E0050", "\U000E0043", "\U000E0034", "\U000E0035",
|
||||
"\U000E002D", "\U000E002A", "\U000E005D", "\U000E002E",
|
||||
"\U000E0026", "\U000E0024", "\U000E0058", "\U000E004E",
|
||||
"\U000E0037", "\U000E0049", "\U000E0051", "\U000E0041",
|
||||
"\U000E0028", "\U000E0027", "\U000E004B", "\U000E005E",
|
||||
"\U000E0044", "\U000E0040", "\U000E004D", "\U000E0056",
|
||||
"\U000E0060", "\U000E0055", "\U000E0030", "\U000E0023",
|
||||
"\U000E0039", "\U000E004F", "\U000E0052", "\U000E002B",
|
||||
"\U000E0057", "\U000E003C", "\U000E0053", "\U000E005B",
|
||||
"\U000E003F", "\U000E0021", "\U000E003B", "\U000E0046",
|
||||
"\U000E0031", "\U000E0059", "\U000E003E", "\U000E0047",
|
||||
"\U000E005C", "\U000E003D", "\U000E0054", "\U000E0048",
|
||||
"\U000E005F", "\U000E0038", "\U000E003A", "\U000E002F",
|
||||
"\U000E005A", "\U000E0020", "\U000E0042", "\U000E0033",
|
||||
"\U000E0036", "\U000E004A", "\U000E0022", "\U000E0045",
|
||||
"\U000E0032", "\U000E002C", "\U000E0029",
|
||||
}
|
||||
)
|
||||
|
||||
func GetCharacterIndex(s string) int {
|
||||
return strings.Index(characterIndex, s)
|
||||
}
|
||||
|
||||
func ZeroWidthCharactersToString(baseStr string) string {
|
||||
|
||||
var completedStr string
|
||||
|
||||
for i := 0; i < len(baseStr); i++ {
|
||||
r := characterReference[GetCharacterIndex(string(baseStr[i]))]
|
||||
if len(r) == 0 {
|
||||
// means we're trying to create a string without a character in the reference
|
||||
return ""
|
||||
}
|
||||
completedStr += r
|
||||
}
|
||||
|
||||
return completedStr
|
||||
}
|
||||
|
||||
// what else am i supposed to call it dumbass
|
||||
func StringToZeroWidthCharacters(encodedStr string) string {
|
||||
|
||||
rL := []rune(encodedStr)
|
||||
var finalStr string
|
||||
|
||||
for _, r := range rL {
|
||||
match := false
|
||||
for i, v := range characterReference {
|
||||
if []rune(v)[0] == r {
|
||||
match = true
|
||||
finalStr += string(characterIndex[i])
|
||||
break
|
||||
}
|
||||
}
|
||||
if !match {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
return finalStr
|
||||
}
|
Loading…
Reference in New Issue