forked from TrueCloudLab/rclone
vendor: update github.com/t3rm1n4l/go-mega and dependencies
This is to fix a crash reported in #3140
This commit is contained in:
parent
48c09608ea
commit
8f89b03d7b
135 changed files with 27990 additions and 605 deletions
5
vendor/github.com/t3rm1n4l/go-mega/.travis.yml
generated
vendored
5
vendor/github.com/t3rm1n4l/go-mega/.travis.yml
generated
vendored
|
@ -4,9 +4,8 @@ osx_image: xcode7.3
|
|||
os:
|
||||
- linux
|
||||
go:
|
||||
- 1.9.x
|
||||
- 1.10.x
|
||||
- 1.11.x
|
||||
- 1.12.x
|
||||
- tip
|
||||
install:
|
||||
- make build_dep
|
||||
|
@ -19,7 +18,7 @@ matrix:
|
|||
- go: tip
|
||||
include:
|
||||
- os: osx
|
||||
go: "1.11.x"
|
||||
go: "1.12.x"
|
||||
env:
|
||||
global:
|
||||
- secure: RzsF80V1i69FVJwKSF8WrFzk5bRUKtPxRkhjiLOO0b1usFg0EIY6XFp3s/VTR6oT91LRXml3Bp7wHHrkPvGnHyUyuxj6loj3gIrsX8cZHUtjyQX/Szfi9MOJpbdJvfCcHByEh9YGldAz//9zvEo5oGuI29Luur3cv+BJNJElmHg=
|
||||
|
|
285
vendor/github.com/t3rm1n4l/go-mega/mega.go
generated
vendored
285
vendor/github.com/t3rm1n4l/go-mega/mega.go
generated
vendored
|
@ -336,7 +336,10 @@ func newMegaFS() *MegaFS {
|
|||
|
||||
func New() *Mega {
|
||||
max := big.NewInt(0x100000000)
|
||||
bigx, _ := rand.Int(rand.Reader, max)
|
||||
bigx, err := rand.Int(rand.Reader, max)
|
||||
if err != nil {
|
||||
panic(err) // this should be returned, but this is a public interface
|
||||
}
|
||||
cfg := newConfig()
|
||||
mgfs := newMegaFS()
|
||||
m := &Mega{
|
||||
|
@ -496,7 +499,10 @@ func (m *Mega) prelogin(email string) error {
|
|||
if len(res[0].Salt) == 0 {
|
||||
return errors.New("prelogin: no salt returned")
|
||||
}
|
||||
m.accountSalt = base64urldecode([]byte(res[0].Salt))
|
||||
m.accountSalt, err = base64urldecode([]byte(res[0].Salt))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
m.accountVersion = res[0].Version
|
||||
|
||||
|
@ -512,8 +518,14 @@ func (m *Mega) login(email string, passwd string) error {
|
|||
|
||||
email = strings.ToLower(email) // mega uses lowercased emails for login purposes
|
||||
|
||||
passkey := password_key(passwd)
|
||||
uhandle := stringhash(email, passkey)
|
||||
passkey, err := password_key(passwd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
uhandle, err := stringhash(email, passkey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.uh = make([]byte, len(uhandle))
|
||||
copy(m.uh, uhandle)
|
||||
|
||||
|
@ -536,9 +548,11 @@ func (m *Mega) login(email string, passwd string) error {
|
|||
msg[0].SessionKey = string(base64urlencode(sessionKey))
|
||||
}
|
||||
|
||||
req, _ := json.Marshal(msg)
|
||||
req, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err = m.api_request(req)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -548,8 +562,14 @@ func (m *Mega) login(email string, passwd string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
m.k = base64urldecode([]byte(res[0].Key))
|
||||
m.k, err = base64urldecode([]byte(res[0].Key))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cipher, err := aes.NewCipher(passkey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cipher.Decrypt(m.k, m.k)
|
||||
m.sid, err = decryptSessionId([]byte(res[0].Privk), []byte(res[0].Csid), m.k)
|
||||
if err != nil {
|
||||
|
@ -634,9 +654,11 @@ func (m *Mega) GetUser() (UserResp, error) {
|
|||
|
||||
msg[0].Cmd = "ug"
|
||||
|
||||
req, _ := json.Marshal(msg)
|
||||
req, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return res[0], err
|
||||
}
|
||||
result, err := m.api_request(req)
|
||||
|
||||
if err != nil {
|
||||
return res[0], err
|
||||
}
|
||||
|
@ -654,7 +676,10 @@ func (m *Mega) GetQuota() (QuotaResp, error) {
|
|||
msg[0].Xfer = 1
|
||||
msg[0].Strg = 1
|
||||
|
||||
req, _ := json.Marshal(msg)
|
||||
req, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return res[0], err
|
||||
}
|
||||
result, err := m.api_request(req)
|
||||
if err != nil {
|
||||
return res[0], err
|
||||
|
@ -671,7 +696,10 @@ func (m *Mega) addFSNode(itm FSNode) (*Node, error) {
|
|||
var node, parent *Node
|
||||
var err error
|
||||
|
||||
master_aes, _ := aes.NewCipher(m.k)
|
||||
master_aes, err := aes.NewCipher(m.k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch {
|
||||
case itm.T == FOLDER || itm.T == FILE:
|
||||
|
@ -680,43 +708,73 @@ func (m *Mega) addFSNode(itm FSNode) (*Node, error) {
|
|||
switch {
|
||||
// File or folder owned by current user
|
||||
case args[0] == itm.User:
|
||||
buf := base64urldecode([]byte(args[1]))
|
||||
buf, err := base64urldecode([]byte(args[1]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = blockDecrypt(master_aes, buf, buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
compkey = bytes_to_a32(buf)
|
||||
compkey, err = bytes_to_a32(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Shared folder
|
||||
case itm.SUser != "" && itm.SKey != "":
|
||||
sk := base64urldecode([]byte(itm.SKey))
|
||||
sk, err := base64urldecode([]byte(itm.SKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = blockDecrypt(master_aes, sk, sk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sk_aes, _ := aes.NewCipher(sk)
|
||||
sk_aes, err := aes.NewCipher(sk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.FS.skmap[itm.Hash] = itm.SKey
|
||||
buf := base64urldecode([]byte(args[1]))
|
||||
buf, err := base64urldecode([]byte(args[1]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = blockDecrypt(sk_aes, buf, buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
compkey = bytes_to_a32(buf)
|
||||
compkey, err = bytes_to_a32(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Shared file
|
||||
default:
|
||||
k := m.FS.skmap[args[0]]
|
||||
b := base64urldecode([]byte(k))
|
||||
b, err := base64urldecode([]byte(k))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = blockDecrypt(master_aes, b, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
block, _ := aes.NewCipher(b)
|
||||
buf := base64urldecode([]byte(args[1]))
|
||||
block, err := aes.NewCipher(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf, err := base64urldecode([]byte(args[1]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = blockDecrypt(block, buf, buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
compkey = bytes_to_a32(buf)
|
||||
compkey, err = bytes_to_a32(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
|
@ -726,10 +784,16 @@ func (m *Mega) addFSNode(itm FSNode) (*Node, error) {
|
|||
key = compkey
|
||||
}
|
||||
|
||||
attr, err = decryptAttr(a32_to_bytes(key), []byte(itm.Attr))
|
||||
// FIXME:
|
||||
bkey, err := a32_to_bytes(key)
|
||||
if err != nil {
|
||||
// FIXME:
|
||||
attr.Name = "BAD ATTRIBUTE"
|
||||
} else {
|
||||
attr, err = decryptAttr(bkey, []byte(itm.Attr))
|
||||
// FIXME:
|
||||
if err != nil {
|
||||
attr.Name = "BAD ATTRIBUTE"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -769,15 +833,33 @@ func (m *Mega) addFSNode(itm FSNode) (*Node, error) {
|
|||
switch {
|
||||
case itm.T == FILE:
|
||||
var meta NodeMeta
|
||||
meta.key = a32_to_bytes(key)
|
||||
meta.iv = a32_to_bytes([]uint32{compkey[4], compkey[5], 0, 0})
|
||||
meta.mac = a32_to_bytes([]uint32{compkey[6], compkey[7]})
|
||||
meta.compkey = a32_to_bytes(compkey)
|
||||
meta.key, err = a32_to_bytes(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
meta.iv, err = a32_to_bytes([]uint32{compkey[4], compkey[5], 0, 0})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
meta.mac, err = a32_to_bytes([]uint32{compkey[6], compkey[7]})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
meta.compkey, err = a32_to_bytes(compkey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
node.meta = meta
|
||||
case itm.T == FOLDER:
|
||||
var meta NodeMeta
|
||||
meta.key = a32_to_bytes(key)
|
||||
meta.compkey = a32_to_bytes(compkey)
|
||||
meta.key, err = a32_to_bytes(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
meta.compkey, err = a32_to_bytes(compkey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
node.meta = meta
|
||||
case itm.T == ROOT:
|
||||
attr.Name = "Cloud Drive"
|
||||
|
@ -814,9 +896,11 @@ func (m *Mega) getFileSystem() error {
|
|||
msg[0].Cmd = "f"
|
||||
msg[0].C = 1
|
||||
|
||||
req, _ := json.Marshal(msg)
|
||||
req, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := m.api_request(req)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -908,9 +992,15 @@ func (m *Mega) NewDownload(src *Node) (*Download, error) {
|
|||
|
||||
mac_enc := cipher.NewCBCEncrypter(aes_block, zero_iv)
|
||||
m.FS.mutex.Lock()
|
||||
t := bytes_to_a32(src.meta.iv)
|
||||
t, err := bytes_to_a32(src.meta.iv)
|
||||
m.FS.mutex.Unlock()
|
||||
iv := a32_to_bytes([]uint32{t[0], t[1], t[0], t[1]})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
iv, err := a32_to_bytes([]uint32{t[0], t[1], t[0], t[1]})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d := &Download{
|
||||
m: m,
|
||||
|
@ -992,10 +1082,17 @@ func (d *Download) DownloadChunk(id int) (chunk []byte, err error) {
|
|||
}
|
||||
|
||||
// Decrypt the block
|
||||
ctr_iv := bytes_to_a32(d.src.meta.iv)
|
||||
ctr_iv, err := bytes_to_a32(d.src.meta.iv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctr_iv[2] = uint32(uint64(chk_start) / 0x1000000000)
|
||||
ctr_iv[3] = uint32(chk_start / 0x10)
|
||||
ctr_aes := cipher.NewCTR(d.aes_block, a32_to_bytes(ctr_iv))
|
||||
bctr_iv, err := a32_to_bytes(ctr_iv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctr_aes := cipher.NewCTR(d.aes_block, bctr_iv)
|
||||
ctr_aes.XORKeyStream(chunk, chunk)
|
||||
|
||||
// Update the chunk_macs
|
||||
|
@ -1035,8 +1132,15 @@ func (d *Download) Finish() (err error) {
|
|||
d.mac_enc.CryptBlocks(mac_data, v)
|
||||
}
|
||||
|
||||
tmac := bytes_to_a32(mac_data)
|
||||
if bytes.Equal(a32_to_bytes([]uint32{tmac[0] ^ tmac[1], tmac[2] ^ tmac[3]}), d.src.meta.mac) == false {
|
||||
tmac, err := bytes_to_a32(mac_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
btmac, err := a32_to_bytes([]uint32{tmac[0] ^ tmac[1], tmac[2] ^ tmac[3]})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if bytes.Equal(btmac, d.src.meta.mac) == false {
|
||||
return EMACMISMATCH
|
||||
}
|
||||
|
||||
|
@ -1188,12 +1292,24 @@ func (m *Mega) NewUpload(parent *Node, name string, fileSize int64) (*Upload, er
|
|||
|
||||
}
|
||||
|
||||
kbytes := a32_to_bytes(ukey[:4])
|
||||
kiv := a32_to_bytes([]uint32{ukey[4], ukey[5], 0, 0})
|
||||
aes_block, _ := aes.NewCipher(kbytes)
|
||||
kbytes, err := a32_to_bytes(ukey[:4])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kiv, err := a32_to_bytes([]uint32{ukey[4], ukey[5], 0, 0})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aes_block, err := aes.NewCipher(kbytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mac_enc := cipher.NewCBCEncrypter(aes_block, zero_iv)
|
||||
iv := a32_to_bytes([]uint32{ukey[4], ukey[5], ukey[4], ukey[5]})
|
||||
iv, err := a32_to_bytes([]uint32{ukey[4], ukey[5], ukey[4], ukey[5]})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
chunks := getChunkSizes(fileSize)
|
||||
|
||||
|
@ -1243,10 +1359,17 @@ func (u *Upload) UploadChunk(id int, chunk []byte) (err error) {
|
|||
if len(chunk) != chk_size {
|
||||
return errors.New("upload chunk is wrong size")
|
||||
}
|
||||
ctr_iv := bytes_to_a32(u.kiv)
|
||||
ctr_iv, err := bytes_to_a32(u.kiv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctr_iv[2] = uint32(uint64(chk_start) / 0x1000000000)
|
||||
ctr_iv[3] = uint32(chk_start / 0x10)
|
||||
ctr_aes := cipher.NewCTR(u.aes_block, a32_to_bytes(ctr_iv))
|
||||
bctr_iv, err := a32_to_bytes(ctr_iv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctr_aes := cipher.NewCTR(u.aes_block, bctr_iv)
|
||||
|
||||
enc := cipher.NewCBCEncrypter(u.aes_block, u.iv)
|
||||
|
||||
|
@ -1324,7 +1447,10 @@ func (u *Upload) Finish() (node *Node, err error) {
|
|||
u.mac_enc.CryptBlocks(mac_data, v)
|
||||
}
|
||||
|
||||
t := bytes_to_a32(mac_data)
|
||||
t, err := bytes_to_a32(mac_data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
meta_mac := []uint32{t[0] ^ t[1], t[2] ^ t[3]}
|
||||
|
||||
attr := FileAttr{u.name}
|
||||
|
@ -1338,7 +1464,10 @@ func (u *Upload) Finish() (node *Node, err error) {
|
|||
u.ukey[2] ^ meta_mac[0], u.ukey[3] ^ meta_mac[1],
|
||||
u.ukey[4], u.ukey[5], meta_mac[0], meta_mac[1]}
|
||||
|
||||
buf := a32_to_bytes(key)
|
||||
buf, err := a32_to_bytes(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
master_aes, err := aes.NewCipher(u.m.k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -1488,9 +1617,11 @@ func (m *Mega) Move(src *Node, parent *Node) error {
|
|||
return err
|
||||
}
|
||||
|
||||
request, _ := json.Marshal(msg)
|
||||
request, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = m.api_request(request)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1515,11 +1646,17 @@ func (m *Mega) Rename(src *Node, name string) error {
|
|||
}
|
||||
var msg [1]FileAttrMsg
|
||||
|
||||
master_aes, _ := aes.NewCipher(m.k)
|
||||
master_aes, err := aes.NewCipher(m.k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
attr := FileAttr{name}
|
||||
attr_data, _ := encryptAttr(src.meta.key, attr)
|
||||
attr_data, err := encryptAttr(src.meta.key, attr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
key := make([]byte, len(src.meta.compkey))
|
||||
err := blockEncrypt(master_aes, key, src.meta.compkey)
|
||||
err = blockEncrypt(master_aes, key, src.meta.compkey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1533,12 +1670,18 @@ func (m *Mega) Rename(src *Node, name string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
req, _ := json.Marshal(msg)
|
||||
req, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = m.api_request(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
src.name = name
|
||||
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create a directory in the filesystem
|
||||
|
@ -1557,12 +1700,21 @@ func (m *Mega) CreateDir(name string, parent *Node) (*Node, error) {
|
|||
compkey[i] = uint32(mrand.Int31())
|
||||
}
|
||||
|
||||
master_aes, _ := aes.NewCipher(m.k)
|
||||
master_aes, err := aes.NewCipher(m.k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
attr := FileAttr{name}
|
||||
ukey := a32_to_bytes(compkey[:4])
|
||||
attr_data, _ := encryptAttr(ukey, attr)
|
||||
ukey, err := a32_to_bytes(compkey[:4])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
attr_data, err := encryptAttr(ukey, attr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key := make([]byte, len(ukey))
|
||||
err := blockEncrypt(master_aes, key, ukey)
|
||||
err = blockEncrypt(master_aes, key, ukey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1578,7 +1730,10 @@ func (m *Mega) CreateDir(name string, parent *Node) (*Node, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
req, _ := json.Marshal(msg)
|
||||
req, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, err := m.api_request(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -1614,14 +1769,20 @@ func (m *Mega) Delete(node *Node, destroy bool) error {
|
|||
return err
|
||||
}
|
||||
|
||||
req, _ := json.Marshal(msg)
|
||||
req, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = m.api_request(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parent := m.FS.lookup[node.hash]
|
||||
parent.removeChild(node)
|
||||
delete(m.FS.lookup, node.hash)
|
||||
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
// process an add node event
|
||||
|
@ -1830,9 +1991,11 @@ func (m *Mega) getLink(n *Node) (string, error) {
|
|||
msg[0].Cmd = "l"
|
||||
msg[0].N = n.GetHash()
|
||||
|
||||
req, _ := json.Marshal(msg)
|
||||
req, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
result, err := m.api_request(req)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
121
vendor/github.com/t3rm1n4l/go-mega/utils.go
generated
vendored
121
vendor/github.com/t3rm1n4l/go-mega/utils.go
generated
vendored
|
@ -37,27 +37,33 @@ func newHttpClient(timeout time.Duration) *http.Client {
|
|||
|
||||
// bytes_to_a32 converts the byte slice b to uint32 slice considering
|
||||
// the bytes to be in big endian order.
|
||||
func bytes_to_a32(b []byte) []uint32 {
|
||||
func bytes_to_a32(b []byte) ([]uint32, error) {
|
||||
length := len(b) + 3
|
||||
a := make([]uint32, length/4)
|
||||
buf := bytes.NewBuffer(b)
|
||||
for i, _ := range a {
|
||||
_ = binary.Read(buf, binary.BigEndian, &a[i])
|
||||
err := binary.Read(buf, binary.BigEndian, &a[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return a
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// a32_to_bytes converts the uint32 slice a to byte slice where each
|
||||
// uint32 is decoded in big endian order.
|
||||
func a32_to_bytes(a []uint32) []byte {
|
||||
func a32_to_bytes(a []uint32) ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
buf.Grow(len(a) * 4) // To prevent reallocations in Write
|
||||
for _, v := range a {
|
||||
_ = binary.Write(buf, binary.BigEndian, v)
|
||||
err := binary.Write(buf, binary.BigEndian, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return buf.Bytes()
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// base64urlencode encodes byte slice b using base64 url encoding.
|
||||
|
@ -79,7 +85,7 @@ func base64urlencode(b []byte) []byte {
|
|||
|
||||
// base64urldecode decodes the byte slice b using base64 url decoding.
|
||||
// It adds required '=' padding before decoding.
|
||||
func base64urldecode(b []byte) []byte {
|
||||
func base64urldecode(b []byte) ([]byte, error) {
|
||||
enc := base64.URLEncoding
|
||||
padSize := 4 - len(b)%4
|
||||
|
||||
|
@ -92,18 +98,29 @@ func base64urldecode(b []byte) []byte {
|
|||
|
||||
decSize := enc.DecodedLen(len(b))
|
||||
buf := make([]byte, decSize)
|
||||
n, _ := enc.Decode(buf, b)
|
||||
return buf[:n]
|
||||
n, err := enc.Decode(buf, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf[:n], err
|
||||
}
|
||||
|
||||
// base64_to_a32 converts base64 encoded byte slice b to uint32 slice.
|
||||
func base64_to_a32(b []byte) []uint32 {
|
||||
return bytes_to_a32(base64urldecode(b))
|
||||
func base64_to_a32(b []byte) ([]uint32, error) {
|
||||
d, err := base64urldecode(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bytes_to_a32(d)
|
||||
}
|
||||
|
||||
// a32_to_base64 converts uint32 slice to base64 encoded byte slice.
|
||||
func a32_to_base64(a []uint32) []byte {
|
||||
return base64urlencode(a32_to_bytes(a))
|
||||
func a32_to_base64(a []uint32) ([]byte, error) {
|
||||
d, err := a32_to_bytes(a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return base64urlencode(d), nil
|
||||
}
|
||||
|
||||
// paddnull pads byte slice b such that the size of resulting byte
|
||||
|
@ -121,10 +138,16 @@ func paddnull(b []byte, q int) []byte {
|
|||
}
|
||||
|
||||
// password_key calculates password hash from the user password.
|
||||
func password_key(p string) []byte {
|
||||
a := bytes_to_a32(paddnull([]byte(p), 4))
|
||||
func password_key(p string) ([]byte, error) {
|
||||
a, err := bytes_to_a32(paddnull([]byte(p), 4))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pkey := a32_to_bytes([]uint32{0x93C467E3, 0x7DB0C7A4, 0xD1BE3F81, 0x0152CB56})
|
||||
pkey, err := a32_to_bytes([]uint32{0x93C467E3, 0x7DB0C7A4, 0xD1BE3F81, 0x0152CB56})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
n := (len(a) + 3) / 4
|
||||
|
||||
|
@ -137,7 +160,14 @@ func password_key(p string) []byte {
|
|||
key[k] = a[k+j]
|
||||
}
|
||||
}
|
||||
ciphers[j/4], _ = aes.NewCipher(a32_to_bytes(key)) // Uses AES in ECB mode
|
||||
bkey, err := a32_to_bytes(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ciphers[j/4], err = aes.NewCipher(bkey) // Uses AES in ECB mode
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
for i := 65536; i > 0; i-- {
|
||||
|
@ -146,24 +176,36 @@ func password_key(p string) []byte {
|
|||
}
|
||||
}
|
||||
|
||||
return pkey
|
||||
return pkey, nil
|
||||
}
|
||||
|
||||
// stringhash computes generic string hash. Uses k as the key for AES
|
||||
// cipher.
|
||||
func stringhash(s string, k []byte) []byte {
|
||||
a := bytes_to_a32(paddnull([]byte(s), 4))
|
||||
func stringhash(s string, k []byte) ([]byte, error) {
|
||||
a, err := bytes_to_a32(paddnull([]byte(s), 4))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h := []uint32{0, 0, 0, 0}
|
||||
for i, v := range a {
|
||||
h[i&3] ^= v
|
||||
}
|
||||
|
||||
hb := a32_to_bytes(h)
|
||||
cipher, _ := aes.NewCipher(k)
|
||||
hb, err := a32_to_bytes(h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cipher, err := aes.NewCipher(k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 16384; i > 0; i-- {
|
||||
cipher.Encrypt(hb, hb)
|
||||
}
|
||||
ha := bytes_to_a32(paddnull(hb, 4))
|
||||
ha, err := bytes_to_a32(paddnull(hb, 4))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return a32_to_base64([]uint32{ha[0], ha[2]})
|
||||
}
|
||||
|
@ -232,14 +274,23 @@ func blockEncrypt(blk cipher.Block, dst, src []byte) error {
|
|||
// key.
|
||||
func decryptSessionId(privk []byte, csid []byte, mk []byte) ([]byte, error) {
|
||||
|
||||
block, _ := aes.NewCipher(mk)
|
||||
pk := base64urldecode(privk)
|
||||
err := blockDecrypt(block, pk, pk)
|
||||
block, err := aes.NewCipher(mk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk, err := base64urldecode(privk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = blockDecrypt(block, pk, pk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := base64urldecode(csid)
|
||||
c, err := base64urldecode(csid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m, _ := getMPI(c)
|
||||
|
||||
|
@ -283,10 +334,17 @@ func decryptAttr(key []byte, data []byte) (attr FileAttr, err error) {
|
|||
if err != nil {
|
||||
return attr, err
|
||||
}
|
||||
iv := a32_to_bytes([]uint32{0, 0, 0, 0})
|
||||
iv, err := a32_to_bytes([]uint32{0, 0, 0, 0})
|
||||
if err != nil {
|
||||
return attr, err
|
||||
}
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
buf := make([]byte, len(data))
|
||||
mode.CryptBlocks(buf, base64urldecode([]byte(data)))
|
||||
ddata, err := base64urldecode([]byte(data))
|
||||
if err != nil {
|
||||
return attr, err
|
||||
}
|
||||
mode.CryptBlocks(buf, ddata)
|
||||
|
||||
if string(buf[:4]) == "MEGA" {
|
||||
str := strings.TrimRight(string(buf[4:]), "\x00")
|
||||
|
@ -313,7 +371,10 @@ func encryptAttr(key []byte, attr FileAttr) (b []byte, err error) {
|
|||
attrib = append(attrib, data...)
|
||||
attrib = paddnull(attrib, 16)
|
||||
|
||||
iv := a32_to_bytes([]uint32{0, 0, 0, 0})
|
||||
iv, err := a32_to_bytes([]uint32{0, 0, 0, 0})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
mode.CryptBlocks(attrib, attrib)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue