<commit_before>﻿module Paket.ConfigFile

open System
open System.Xml
open System.Security.Cryptography
open System.Text
open System.IO

open Chessie.ErrorHandling
open Paket.Domain
open Paket.Xml
open Paket.Logging
open Paket.Utils

let private rootElement = "configuration"

let private getConfigNode (nodeName : string) =
    let rootNode = 
        let doc = new XmlDocument()
        if File.Exists Constants.PaketConfigFile then 
            try 
                doc.Load Constants.PaketConfigFile
                ok doc.DocumentElement
            with _ -> fail ConfigFileParseError
        else
            let element = doc.CreateElement rootElement
            doc.AppendChild(element) |> ignore
            ok element

    trial {
        let! root = rootNode
        let node = 
            match root |> getNode nodeName with
            | None -> root.OwnerDocument.CreateElement nodeName
                      |> root.AppendChild
            | Some node -> node
        return node
    }


let private saveConfigNode (node : XmlNode) =
    trial {
        do! createDir Constants.PaketConfigFolder
        do! saveFile Constants.PaketConfigFile (node.OwnerDocument.OuterXml)
    }

let private cryptoServiceProvider = new RNGCryptoServiceProvider()

let private getRandomSalt() =
    let saltSize = 8
    let saltBytes = Array.create saltSize ( new Byte() )
    cryptoServiceProvider.GetNonZeroBytes(saltBytes)
    saltBytes

/// Encrypts a string with a user specific keys
let Encrypt (password : string) = 
    let salt = getRandomSalt()
    let encryptedPassword = ProtectedData.Protect(Encoding.UTF8.GetBytes password, salt, DataProtectionScope.CurrentUser)
    salt |> Convert.ToBase64String ,
    encryptedPassword |> Convert.ToBase64String

/// Decrypt a encrypted string with a user specific keys
let Decrypt (salt : string) (encrypted : string) =
    ProtectedData.Unprotect(Convert.FromBase64String encrypted, Convert.FromBase64String salt, DataProtectionScope.CurrentUser)
    |> Encoding.UTF8.GetString

let DecryptNuget (encrypted : string) = 
    ProtectedData.Unprotect(Convert.FromBase64String encrypted, Encoding.UTF8.GetBytes "NuGet", DataProtectionScope.CurrentUser)
    |> Encoding.UTF8.GetString

let private readPassword (message : string) : string = 
    Console.Write(message)
    let mutable continueLooping = true<commit_msg>ConfigFile: password encryption does not work on specific machine configurations. This is the minimal fix to make password encryption work in our environment. seealso issue: #1346<commit_after>﻿module Paket.ConfigFile

open System
open System.Xml
open System.Security.Cryptography
open System.Text
open System.IO

open Chessie.ErrorHandling
open Paket.Domain
open Paket.Xml
open Paket.Logging
open Paket.Utils

let private rootElement = "configuration"

let private getConfigNode (nodeName : string) =
    let rootNode = 
        let doc = new XmlDocument()
        if File.Exists Constants.PaketConfigFile then 
            try 
                doc.Load Constants.PaketConfigFile
                ok doc.DocumentElement
            with _ -> fail ConfigFileParseError
        else
            let element = doc.CreateElement rootElement
            doc.AppendChild(element) |> ignore
            ok element

    trial {
        let! root = rootNode
        let node = 
            match root |> getNode nodeName with
            | None -> root.OwnerDocument.CreateElement nodeName
                      |> root.AppendChild
            | Some node -> node
        return node
    }


let private saveConfigNode (node : XmlNode) =
    trial {
        do! createDir Constants.PaketConfigFolder
        do! saveFile Constants.PaketConfigFile (node.OwnerDocument.OuterXml)
    }

let private cryptoServiceProvider = new RNGCryptoServiceProvider()

let private getRandomSalt() =
    let saltSize = 8
    let saltBytes = Array.create saltSize ( new Byte() )
    cryptoServiceProvider.GetNonZeroBytes(saltBytes)
    saltBytes

/// Encrypts a string with a user specific keys
let Encrypt (password : string) = 
    let salt = getRandomSalt()
    let encryptedPassword = ProtectedData.Protect(Encoding.UTF8.GetBytes password, salt, DataProtectionScope.LocalMachine)
    salt |> Convert.ToBase64String ,
    encryptedPassword |> Convert.ToBase64String

/// Decrypt a encrypted string with a user specific keys
let Decrypt (salt : string) (encrypted : string) =
    ProtectedData.Unprotect(Convert.FromBase64String encrypted, Convert.FromBase64String salt, DataProtectionScope.CurrentUser)
    |> Encoding.UTF8.GetString

let DecryptNuget (encrypted : string) = 
    ProtectedData.Unprotect(Convert.FromBase64String encrypted, Encoding.UTF8.GetBytes "NuGet", DataProtectionScope.CurrentUser)
    |> Encoding.UTF8.GetString

let private readPassword (message : string) : string = 
    Console.Write(message)
    let mutable continueLooping = true
{'fraction_non_alphanumeric': 0.0679730557256583, 'fraction_numerical': 0.00694019187589304, 'mean_word_length': 3.049586776859504, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4984159', 'n_tokens_mistral': 1380, 'n_tokens_neox': 1301, 'n_words': 378}