//go:build windows

package main

// Parolalar Windows DPAPI ile sifrelenir: anahtar bu Windows kullanicisina baglidir,
// baska bir hesapta veya baska bir bilgisayarda cozulmez. Ayar dosyasinda yalnizca sifreli hali tutulur.

import (
	"errors"
	"syscall"
	"unsafe"
)

const cryptprotectUIForbidden = 0x1

type dataBlob struct {
	cbData uint32
	pbData *byte
}

var (
	modCrypt32      = syscall.NewLazyDLL("crypt32.dll")
	procProtectData = modCrypt32.NewProc("CryptProtectData")
	procUnprotect   = modCrypt32.NewProc("CryptUnprotectData")
	modKernelDpapi  = syscall.NewLazyDLL("kernel32.dll")
	procLocalFree   = modKernelDpapi.NewProc("LocalFree")
)

// blobKopyala: DPAPI'nin ayirdigi bellegi Go dilimine kopyalar ve LocalFree ile serbest birakir.
func blobKopyala(b dataBlob) []byte {
	if b.pbData == nil || b.cbData == 0 {
		return nil
	}
	defer procLocalFree.Call(uintptr(unsafe.Pointer(b.pbData)))
	kopya := make([]byte, b.cbData)
	copy(kopya, unsafe.Slice(b.pbData, b.cbData))
	return kopya
}

// dpapiSifrele: veriyi bu kullanici icin sifreler.
func dpapiSifrele(veri []byte) ([]byte, error) {
	if len(veri) == 0 {
		return nil, errors.New("boş veri")
	}
	in := dataBlob{cbData: uint32(len(veri)), pbData: &veri[0]}
	var out dataBlob
	r, _, _ := procProtectData.Call(uintptr(unsafe.Pointer(&in)), 0, 0, 0, 0,
		cryptprotectUIForbidden, uintptr(unsafe.Pointer(&out)))
	if r == 0 {
		return nil, errors.New("DPAPI şifreleme başarısız")
	}
	return blobKopyala(out), nil
}

// dpapiCoz: DPAPI ile sifrelenmis veriyi cozer. Baska kullanicida ya da bozuk veride hata doner.
func dpapiCoz(sifreli []byte) ([]byte, error) {
	if len(sifreli) == 0 {
		return nil, errors.New("boş veri")
	}
	in := dataBlob{cbData: uint32(len(sifreli)), pbData: &sifreli[0]}
	var out dataBlob
	r, _, _ := procUnprotect.Call(uintptr(unsafe.Pointer(&in)), 0, 0, 0, 0,
		cryptprotectUIForbidden, uintptr(unsafe.Pointer(&out)))
	if r == 0 {
		return nil, errors.New("DPAPI çözme başarısız")
	}
	return blobKopyala(out), nil
}
