Reputation: 887
I'm writing a simple rc4 encryption/decryption utility as a first project. I'm stuck on trying to convert the given string into an array of bytes that can then be manipulated by the core algorithm. How do you convert a string into an array of bytes in functional f#?
//From another thread
let private replace find (repl : string) (str : string) = str.Replace(find, repl)
//let private algorithm bytes = blah blah blah
let Encrypt (decrypted : string) =
decrypted.Chars
|> Array.map(fun c -> byte.Parse(c)) // This line is clearly not working
// |> algorithm
|> BitConverter.ToString
|> replace "-" ""
FYI in C# it looks like:
public static string Encrypt(string decrypted)
{
byte[] bytes = new byte[decrypted.Length];
for (int i = 0; i < decrypted.Length; ++i)
bytes[i] = (byte)decrypted[i];
Algorithm(ref bytes);
return BitConverter.ToString(bytes).Replace("-", "").ToLower();
}
Upvotes: 9
Views: 8089
Reputation: 887
As per Gradbot's request, the final code looks like:
1) I don't like the casts to byte
2) The main algorithm function looks very un-functional
Constructive criticism is welcome.
Rc4.fs
#light
open System
open MiscUtils
open StringUtils
let private key = "Mykey"B
let private byteMask = 0xff
let private byteMax = byteMask
let private algorithm (bytes : byte[]) =
let mutable j = 0
let mutable i = 0
let mutable s = [| for c in 0 .. byteMax -> (byte) c |]
for i in 0 .. byteMax do
j <- (j + (int) (s.[i] + key.[i % key.GetLength(0)])) &&& byteMask
Swap (&s.[i]) (&s.[j])
i <- 0
j <- 0
for x in 0 .. bytes.Length - 1 do
i <- (i + 1) &&& byteMask
j <- (j + (int) s.[i]) &&& byteMask
Swap (&s.[i]) (&s.[j])
let mutable t = (int)(s.[i] + s.[j]) &&& byteMask
bytes.[x] <- bytes.[x] ^^^ s.[t]
bytes
let Encrypt (decrypted : string) =
Text.Encoding.ASCII.GetBytes decrypted
|> algorithm
|> BitConverter.ToString
|> ToLower
|> Replace "-" ""
let Decrypt (encrypted : string) =
[| for i in 0 .. 2 .. encrypted.Length - 1 -> Convert.ToByte(encrypted.Substring(i, 2), 16) |]
|> algorithm
|> System.Text.Encoding.ASCII.GetString
StringUtils.Fs
#light
let Replace find (repl : string) (str : string) = str.Replace(find, repl)
let ToLower (str : string) = str.ToLower()
MiscUtils.fs
#light
let Swap (left : 'a byref) (right : 'a byref) =
let temp = left
left <- right
right <- temp
Upvotes: 3
Reputation: 13862
you could do a direct translation
let Encrypt(decrypted : string) =
let bytes = Array.init decrypted.Length (fun i -> byte decrypted.[i])
Algorithm(ref bytes)
BitConverter.ToString(bytes).Replace("-", "").ToLower()
Upvotes: 1
Reputation: 81516
Although you could write your own function to do the job, its best to stick with the built-in .NET methods:
String to bytes:
System.Text.Encoding.ASCII.GetBytes("hello world!")
Bytes to string:
System.Text.Encoding.ASCII.GetString([|104uy; 101uy; 108uy; 108uy;
111uy; 32uy; 119uy; 111uy; 114uy; 108uy; 100uy; 33uy|])
Upvotes: 12