Has anyone gotten Dpapi and Roaming Profiles to work?

176 views Asked by At

According to Microsoft, DPAPI should be able to encrypt data on one machine, and decrypt it on another:

See: https://support.microsoft.com/en-us/topic/bf374083-626f-3446-2a9d-3f6077723a60#bkmk_6

When I am logged into a domain controller, and encrypt a file, I expect to be able to log out, transfer and decrypt it on another machine logged in on the same user.

However, I get this error:

error: (-2146893813, 'CryptProtectData', 'Key not valid for use in specified state.')

Which implies that the "roaming" didn't work. I'm assuming there are some group policy things I need to set to get those creds to roam properly.

Also, if there's a better way to do this (some other api to use the logged-in user's existing creds), I'm ok with that.

Here's the script I use to test:

import argparse
import os
import sys

from win32crypt import CryptProtectData, CryptUnprotectData


def dpapi_encrypt(fin, fout):
    dat = fin.read()
    fout.write(CryptProtectData(dat))


def dpapi_decrypt(fin, fout):
    (_descr, dat) = CryptUnprotectData(fin.read())
    if dat and dat[-1] == 0:
        dat = dat[:-1]
    fout.write(dat)


def do_fileop(file, op):
    if file == "-":
        fin = sys.stdin.buffer
        fout = sys.stdout.buffer
        op(fin, fout)
    else:
        with open(file, "rb") as fin:
            tmp = file + ".dpapi-enc"
            with open(tmp, "wb") as fout:
                op(fin, fout)
        os.replace(tmp, file)


def encrypt_file(file):
    do_fileop(file, dpapi_encrypt)


def decrypt_file(file):
    do_fileop(file, dpapi_decrypt)


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("file")
    parser.add_argument("--encrypt", "-e", action="store_true")
    parser.add_argument("--decrypt", "-d", action="store_true")
    args = parser.parse_args()

    if args.encrypt:
        encrypt_file(args.file)
    elif args.decrypt:
        decrypt_file(args.file)
    else:
        print("error: specify --encrypt or --decrypt", file=sys.stdout)


if __name__ == "__main__":
    main()
0

There are 0 answers