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()