How to retrieve a 'crypt' password from a config file

This is my attempt at trying to help people from dozens of other threads with this problem. Since these threads are all closed I'm creating this one.

The password that is saved on crypt remotes on ~/.config/rclone.conf is encrypted with a hardcoded key, therefore it can be recovered.

I've copied some code from the rclone source tree and added a line to make it easier for people to run it.

Just go to https://play.golang.org/p/IcRYDip3PnE and replace the string YOUR PSEUDO-ENCRYPTED PASSWORD HERE with the actual password that is written in your ~/.config/rclone.conf file, then click "Run".

This is the code for future reference:

package main

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/base64"
	"errors"
	"fmt"
	"log"
)

// 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 cipher.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 := cipher.NewCTR(cryptBlock, iv)
	stream.XORKeyStream(out, in)
	return nil
}

// Reveal an obscured value
func Reveal(x string) (string, error) {
	ciphertext, err := base64.RawURLEncoding.DecodeString(x)
	if err != nil {
		return "", fmt.Errorf("base64 decode failed when revealing password - is it obscured? %w", err)
	}
	if len(ciphertext) < aes.BlockSize {
		return "", errors.New("input too short when revealing password - is it obscured?")
	}
	buf := ciphertext[aes.BlockSize:]
	iv := ciphertext[:aes.BlockSize]
	if err := crypt(buf, buf, iv); err != nil {
		return "", fmt.Errorf("decrypt failed when revealing password - is it obscured? %w", err)
	}
	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
}

func main() {
	fmt.Println(MustReveal("YOUR PSEUDO-ENCRYPTED PASSWORD HERE"))
}

(Based on some answer I read in one of these threads but I don't remember where anymore. Thank you!)

4 Likes

Im sorry for stupid question but, this will show the rclone config password if you paste the obfuscated password in configfile?

yes, it works well, so why not try it yourself?

you can also take the code from the website and create a execuable file.
that is what i did

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.