-
-
Save FWeinb/03cfba821b2d305414cbf2e5bc720157 to your computer and use it in GitHub Desktop.
Rclone filename gopherjs wrapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"crypto/aes" | |
gocipher "crypto/cipher" | |
"crypto/rand" | |
"encoding/base64" | |
"log" | |
"github.com/gopherjs/gopherjs/js" | |
"github.com/pkg/errors" | |
) | |
func main() { | |
js.Global.Set("Decrypter", map[string]interface{}{ | |
"Create": New, | |
}) | |
} | |
type Crypt struct { | |
_c Cipher | |
} | |
type Callback func(err error, value interface{}) | |
// Crypt | |
func New(options *js.Object, cb Callback) { | |
defer func() { | |
pass := options.Get("pass").String() | |
salt := options.Get("salt").String() | |
c, err := newCipher(NameEncryptionStandard, mustReveal(pass), mustReveal(salt)) | |
cb(err, js.MakeWrapper(&Crypt{c})) | |
}() | |
} | |
func (c *Crypt) DecryptFileName(str string, cb Callback) { | |
defer func() { | |
plain, err := c._c.DecryptFileName(str) | |
cb(err, plain) | |
}() | |
} | |
func (c *Crypt) EncryptFileName(str string, cb Callback) { | |
defer func() { | |
plain := c._c.EncryptFileName(str) | |
cb(nil, plain) | |
}() | |
} | |
// crypt internals | |
var ( | |
cryptKey = []byte{ | |
0x9c, 0x93, 0x5b, 0x48, 0x73, 0x0a, 0x55, 0x4d, | |
0x6b, 0xfd, 0x7c, 0x63, 0xc8, 0x86, 0xa9, 0x2b, | |
0xd3, 0x90, 0x19, 0x8e, 0xb8, 0x12, 0x8a, 0xfb, | |
0xf4, 0xde, 0x16, 0x2b, 0x8b, 0x95, 0xf6, 0x38, | |
} | |
cryptBlock gocipher.Block | |
cryptRand = rand.Reader | |
) | |
// crypt transforms in to out using iv under AES-CTR. | |
// | |
// in and out may be the same buffer. | |
// | |
// Note encryption and decryption are the same operation | |
func crypt(out, in, iv []byte) error { | |
if cryptBlock == nil { | |
var err error | |
cryptBlock, err = aes.NewCipher(cryptKey) | |
if err != nil { | |
return err | |
} | |
} | |
stream := gocipher.NewCTR(cryptBlock, iv) | |
stream.XORKeyStream(out, in) | |
return nil | |
} | |
func reveal(x string) (string, error) { | |
ciphertext, err := base64.RawURLEncoding.DecodeString(x) | |
if err != nil { | |
return "", errors.Wrap(err, "base64 decode failed") | |
} | |
if len(ciphertext) < aes.BlockSize { | |
return "", errors.New("input too short") | |
} | |
buf := ciphertext[aes.BlockSize:] | |
iv := ciphertext[:aes.BlockSize] | |
if err := crypt(buf, buf, iv); err != nil { | |
return "", errors.Wrap(err, "decrypt failed") | |
} | |
return string(buf), nil | |
} | |
// MustReveal reveals an obscured value, exiting with a fatal error if it failed | |
func mustReveal(x string) string { | |
out, err := reveal(x) | |
if err != nil { | |
log.Fatalf("Reveal failed: %v", err) | |
} | |
return out | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment