Encrypting and decrypting audio clip to file unity - c#

I'm using AES for encrypting and decrypting, I can write it to a file and when I try to read the file back to audio clip, I'm getting input exception
I tried to convert the audio file to base64 byte array while saving in file so that when I read the file I can read it as byte array which is required for creating audio clip
I have attached the code below
private float[] ConvertByteToFloat(byte[] array)
{
float[] floatArr = new float[array.Length / 4];
for (int i = 0; i < floatArr.Length; i++)
{
if (BitConverter.IsLittleEndian)
{
Array.Reverse(array, i * 4, 4);
}
floatArr[i] = BitConverter.ToSingle(array, i * 4) / 0x80000000;
}
return floatArr;
}
public void ReadFile()
{
// Does the file exist AND does the "key" preference exist?
if (File.Exists(saveFile) && PlayerPrefs.HasKey("Key"))
{
// Update key based on PlayerPrefs
// (Convert the String into a Base64 byte[] array.)
byte[] savedKey = Convert.FromBase64String(PlayerPrefs.GetString("Key"));
byte[] savedIV = Convert.FromBase64String(PlayerPrefs.GetString("IV"));
// Create FileStream for opening files.
dataStream = new FileStream(saveFile, FileMode.Open);
Debug.Log(PlayerPrefs.GetString("Key"));
// Create new AES instance.
Aes oAes = Aes.Create();
// Create an array of correct size based on AES IV.
byte[] outputIV = new byte[savedIV.Length];
// Read the IV from the file.
dataStream.Read(savedIV, 0, outputIV.Length);
// Create CryptoStream, wrapping FileStream
CryptoStream oStream = new CryptoStream(dataStream, oAes.CreateDecryptor(savedKey, outputIV), CryptoStreamMode.Read);
// Create a StreamReader, wrapping CryptoStream
StreamReader reader = new StreamReader(oStream);
// Read the entire file into a String value.
string text = reader.ReadToEnd();
byte[] songDataBytes = Convert.FromBase64String(text);
AudioClip audioClip = AudioClip.Create("SongName", songDataBytes.Length, 1, 48000, false);
float[] f = ConvertByteToFloat(songDataBytes);
audioClip.SetData(f, 0);
ass.clip = audioClip;
ass.Play();
Debug.Log("C");
// Deserialize the JSON data
// into a pattern matching the GameData class.
//gameData = JsonUtility.FromJson<GameData>(text);
}
Debug.Log("D");
}
public void WriteFile()
{
string songLoc = Application.persistentDataPath + "/song.mp3";
// Create new AES instance.
Aes iAes = Aes.Create();
// Update the internal key.
string key = PlayerPrefs.GetString("Key");
string IV = PlayerPrefs.GetString("Key");
byte[] savedKey;
byte[] savedIV;
if (key == "")
{
iAes.GenerateIV();
savedKey = iAes.Key;
savedIV = iAes.IV;
key = Convert.ToBase64String(savedKey);
IV = Convert.ToBase64String(savedIV);
}
else
{
savedIV = Convert.FromBase64String(PlayerPrefs.GetString("IV"));
savedKey = Convert.FromBase64String(PlayerPrefs.GetString("Key"));
}
Debug.Log(key);
// Convert the byte[] into a Base64 String.
//string key = System.Convert.ToBase64String(savedKey);
// Update the PlayerPrefs
PlayerPrefs.SetString("Key", key);
PlayerPrefs.SetString("IV", IV);
// Create a FileStream for creating files.
dataStream = new FileStream(saveFile, FileMode.Create);
// Save the new generated IV.
byte[] inputIV = savedIV;
// Write the IV to the FileStream unencrypted.
dataStream.Write(inputIV, 0, inputIV.Length);
// Create CryptoStream, wrapping FileStream.
CryptoStream iStream = new CryptoStream(dataStream, iAes.CreateEncryptor(savedKey, savedIV), CryptoStreamMode.Write);
// Create StreamWriter, wrapping CryptoStream.
StreamWriter sWriter = new StreamWriter(iStream);
// Serialize the object into JSON and save string.
byte[] songData = File.ReadAllBytes(songLoc);
//string songString = Convert.ToBase64String(songData);
//File.WriteAllBytes(saveFile, songData);
// Write to the innermost stream (which will encrypt).
sWriter.BaseStream.Write(songData, 0, songData.Length);
// Close StreamWriter.
sWriter.Close();
// Close CryptoStream.
iStream.Close();
// Close FileStream.
dataStream.Close();
}

Related

CryptoStream behaves differently on local and aws

I have encryption decryption code which is perfectly working fine in local. From local system using code first approach I created database in aws which created successfully with seeds values in which I have decrypted the password.
Now, I have published the .net6 application in aws ec2 instance. On logging it is giving error of incorrect credentials.
I have logged the username and passwords and rechecked the scenario. The issue I have found is the encryption is changed.
I have updated the password and successfully logged in. But now the problem is with roles. I have applied checks on encrypted role ids which are not maching now.
Can anyone please help me here on this issue please?
`
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Common
{
public static class EncyptionDcryption
{
static string key = "85OIbnI9";
static string vector = "eH90BDl0";
////////////////////////////////////////////////////////////////////////////////
// Decryption
////////////////////////////////////////////////////////////////////////////////
public static string GetDecryptedText(string txt)
{
txt = txt.Replace(' ', '+');
DESCryptoServiceProvider key = new DESCryptoServiceProvider();
key.Key = ASCIIEncoding.ASCII.GetBytes(key); // decryption key
key.IV = ASCIIEncoding.ASCII.GetBytes(vector);// initialization vector
int length = txt.Length;
byte[] buffer = new byte[length];
buffer = Convert.FromBase64String(txt);
string decText = Decrypt(buffer, key);
return decText;
}
public static string Decrypt(byte[] CypherText, SymmetricAlgorithm key)
{
// Create a memory stream to the passed buffer.
MemoryStream ms = new MemoryStream(CypherText);
// Create a CryptoStream using the memory stream and the
// CSP DES key.
CryptoStream encStream = new CryptoStream(ms, key.CreateDecryptor(), CryptoStreamMode.Read);
// Create a StreamReader for reading the stream.
StreamReader sr = new StreamReader(encStream);
// Read the stream as a string.
string val = sr.ReadLine();
// Close the streams.
sr.Close();
encStream.Close();
ms.Close();
return val;
}
////////////////////////////////////////////////////////////////////////////////
// Encryption
////////////////////////////////////////////////////////////////////////////////
public static byte[] Encrypt(string PlainText, SymmetricAlgorithm key)
{
// Create a memory stream.
MemoryStream ms = new MemoryStream();
// Create a CryptoStream using the memory stream and the
// CSP DES key.
CryptoStream encStream = new CryptoStream(ms, key.CreateEncryptor(), CryptoStreamMode.Write);
// Create a StreamWriter to write a string
// to the stream.
StreamWriter sw = new StreamWriter(encStream);
// Write the plaintext to the stream.
sw.WriteLine(PlainText);
// Close the StreamWriter and CryptoStream.
sw.Close();
encStream.Close();
// Get an array of bytes that represents
// the memory stream.
byte[] buffer = ms.ToArray();
// Close the memory stream.
ms.Close();
// Return the encrypted byte array.
return buffer;
}
public static string GetEncryptedText(string txt)
{
DESCryptoServiceProvider key = new DESCryptoServiceProvider();
key.Key = ASCIIEncoding.ASCII.GetBytes(key); // decryption key
key.IV = ASCIIEncoding.ASCII.GetBytes(vector);// initialization vector
// Encrypt a string to a byte array.
byte[] buffer = Encrypt(txt, key);
string encText;
encText = Convert.ToBase64String(buffer);
return encText;
}
}
}
`
Why it behaves differently on server and local? But no clue.

How to convert this file to top-level statement?

I am using .NET 6 , Visual Studio 2022 Preview on Windows 11 pro x64.
using System;
using System.IO;
using System.Security.Cryptography;
public class HMACSHA512example
{
public static void Main(string[] Fileargs)
{
string dataFile;
string signedFile;
//If no file names are specified, create them.
if (Fileargs.Length < 2)
{
dataFile = #"text.txt";
signedFile = "signedFile.enc";
if (!File.Exists(dataFile))
{
// Create a file to write to.
using (StreamWriter sw = File.CreateText(dataFile))
{
sw.WriteLine("Here is a message to sign");
}
}
}
else
{
dataFile = Fileargs[0];
signedFile = Fileargs[1];
}
try
{
// Create a random key using a random number generator. This would be the
// secret key shared by sender and receiver.
byte[] secretkey = new Byte[64];
//RNGCryptoServiceProvider is an implementation of a random number generator.
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
// The array is now filled with cryptographically strong random bytes.
rng.GetBytes(secretkey);
// Use the secret key to sign the message file.
SignFile(secretkey, dataFile, signedFile);
// Verify the signed file
VerifyFile(secretkey, signedFile);
}
}
catch (IOException e)
{
Console.WriteLine("Error: File not found", e);
}
} //end main
// Computes a keyed hash for a source file and creates a target file with the keyed hash
// prepended to the contents of the source file.
public static void SignFile(byte[] key, String sourceFile, String destFile)
{
// Initialize the keyed hash object.
using (HMACSHA512 hmac = new HMACSHA512(key))
{
using (FileStream inStream = new FileStream(sourceFile, FileMode.Open))
{
using (FileStream outStream = new FileStream(destFile, FileMode.Create))
{
// Compute the hash of the input file.
byte[] hashValue = hmac.ComputeHash(inStream);
// Reset inStream to the beginning of the file.
inStream.Position = 0;
// Write the computed hash value to the output file.
outStream.Write(hashValue, 0, hashValue.Length);
// Copy the contents of the sourceFile to the destFile.
int bytesRead;
// read 1K at a time
byte[] buffer = new byte[1024];
do
{
// Read from the wrapping CryptoStream.
bytesRead = inStream.Read(buffer, 0, 1024);
outStream.Write(buffer, 0, bytesRead);
} while (bytesRead > 0);
}
}
}
return;
} // end SignFile
// Compares the key in the source file with a new key created for the data portion of the file. If the keys
// compare the data has not been tampered with.
public static bool VerifyFile(byte[] key, String sourceFile)
{
bool err = false;
// Initialize the keyed hash object.
using (HMACSHA512 hmac = new HMACSHA512(key))
{
// Create an array to hold the keyed hash value read from the file.
byte[] storedHash = new byte[hmac.HashSize / 8];
// Create a FileStream for the source file.
using (FileStream inStream = new FileStream(sourceFile, FileMode.Open))
{
// Read in the storedHash.
inStream.Read(storedHash, 0, storedHash.Length);
// Compute the hash of the remaining contents of the file.
// The stream is properly positioned at the beginning of the content,
// immediately after the stored hash value.
byte[] computedHash = hmac.ComputeHash(inStream);
// compare the computed hash with the stored value
for (int i = 0; i < storedHash.Length; i++)
{
if (computedHash[i] != storedHash[i])
{
err = true;
}
}
}
}
if (err)
{
Console.WriteLine("Hash values differ! Signed file has been tampered with!");
return false;
}
else
{
Console.WriteLine("Hash values agree -- no tampering occurred.");
return true;
}
} //end VerifyFile
} //end class
Source: https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.hmacsha512?view=net-6.0
How to convert this file to top-level statement?
You just have to move your main to the top level, and keep the methods.
using System.Security.Cryptography;
string dataFile;
string signedFile;
//If no file names are specified, create them.
if (args.Length < 2)
{
dataFile = #"text.txt";
signedFile = "signedFile.enc";
if (!File.Exists(dataFile))
{
// Create a file to write to.
using (StreamWriter sw = File.CreateText(dataFile))
{
sw.WriteLine("Here is a message to sign");
}
}
}
else
{
dataFile = args[0];
signedFile = args[1];
}
try
{
// Create a random key using a random number generator. This would be the
// secret key shared by sender and receiver.
byte[] secretkey = new Byte[64];
//RNGCryptoServiceProvider is an implementation of a random number generator.
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
// The array is now filled with cryptographically strong random bytes.
rng.GetBytes(secretkey);
// Use the secret key to sign the message file.
SignFile(secretkey, dataFile, signedFile);
// Verify the signed file
VerifyFile(secretkey, signedFile);
}
}
catch (IOException e)
{
Console.WriteLine("Error: File not found", e);
}
// Computes a keyed hash for a source file and creates a target file with the keyed hash
// prepended to the contents of the source file.
static void SignFile(byte[] key, String sourceFile, String destFile)
{
// Initialize the keyed hash object.
using (HMACSHA512 hmac = new HMACSHA512(key))
{
using (FileStream inStream = new FileStream(sourceFile, FileMode.Open))
{
using (FileStream outStream = new FileStream(destFile, FileMode.Create))
{
// Compute the hash of the input file.
byte[] hashValue = hmac.ComputeHash(inStream);
// Reset inStream to the beginning of the file.
inStream.Position = 0;
// Write the computed hash value to the output file.
outStream.Write(hashValue, 0, hashValue.Length);
// Copy the contents of the sourceFile to the destFile.
int bytesRead;
// read 1K at a time
byte[] buffer = new byte[1024];
do
{
// Read from the wrapping CryptoStream.
bytesRead = inStream.Read(buffer, 0, 1024);
outStream.Write(buffer, 0, bytesRead);
} while (bytesRead > 0);
}
}
}
return;
} // end SignFile
// Compares the key in the source file with a new key created for the data portion of the file. If the keys
// compare the data has not been tampered with.
static bool VerifyFile(byte[] key, String sourceFile)
{
bool err = false;
// Initialize the keyed hash object.
using (HMACSHA512 hmac = new HMACSHA512(key))
{
// Create an array to hold the keyed hash value read from the file.
byte[] storedHash = new byte[hmac.HashSize / 8];
// Create a FileStream for the source file.
using (FileStream inStream = new FileStream(sourceFile, FileMode.Open))
{
// Read in the storedHash.
inStream.Read(storedHash, 0, storedHash.Length);
// Compute the hash of the remaining contents of the file.
// The stream is properly positioned at the beginning of the content,
// immediately after the stored hash value.
byte[] computedHash = hmac.ComputeHash(inStream);
// compare the computed hash with the stored value
for (int i = 0; i < storedHash.Length; i++)
{
if (computedHash[i] != storedHash[i])
{
err = true;
}
}
}
}
if (err)
{
Console.WriteLine("Hash values differ! Signed file has been tampered with!");
return false;
}
else
{
Console.WriteLine("Hash values agree -- no tampering occurred.");
return true;
}
} //end VerifyFile

Decryption providing a padding error

I'm trying to save a serialized object to an encrypted file. This isn't production quality and I am aware of the security risks with the way that I am doing this, but ignoring those I will have a key in a resource (data.Settings.key) that wont change and I have a salt that is also a constant.
My encryption seems to work, but decryption returns me an Exception saying that padding is invalid and cannot be closed when I try to close my CryptoStream.
private static byte[] decrypt(byte[] bytes)
{
var decryptor = algorithm.CreateDecryptor();
using (var sMemoryStream = new MemoryStream())
using (var sCryptoStream = new CryptoStream(sMemoryStream, decryptor, CryptoStreamMode.Write))
{
sCryptoStream.Write(bytes, 0, bytes.Length);
sCryptoStream.Close();
return sMemoryStream.ToArray();
}
}
The algorithm variable is the same one that the encrypt method uses and is built by this method which is called in the classes constructor:
private static SymmetricAlgorithm GetAlgorithm()
{
var algorithm = Rijndael.Create();
// Create key from salt and password in config
var rdb = new Rfc2898DeriveBytes(data.Settings.key, new byte[] {
0x44,0x61,0x79,0x6e,0x65,0x44,0x6f,0x75,0x67,0x61,0x6e
});
algorithm.Padding = PaddingMode.PKCS7;
// Set key and IV from rdb
algorithm.Key = rdb.GetBytes(32);
algorithm.IV = rdb.GetBytes(16);
return algorithm;
}
I've tried changing the padding mode in the algorithm but I can't understand why it's fine with this padding when encrypting, but now when decrypting.
If it helps here is the method that calls the decrypt method:
private static User OpenFile(String sUserName)
{
Console.WriteLine("Opening file...");
using (Stream sFileStream = new FileStream(data.Settings.dir + "data\\accounts\\" + sUserName + ".dat",
FileMode.Open, FileAccess.Read, FileShare.None))
using (Stream sMemoryStream = new MemoryStream())
{
// Read from File to memory stream
sFileStream.CopyTo(sMemoryStream);
// Decrypt data and store in new memory stream
byte[] bytes = new byte[sMemoryStream.Length];
Console.WriteLine("\tb:" + bytes.Length);
bytes = decrypt(bytes);
Console.WriteLine("\ta:" + bytes.Length);
Stream stream = new MemoryStream(bytes);
Console.WriteLine("\ts:" + bytes.Length);
// Deserialise memory stream and return as User object
User user = (User)bfFormatter.Deserialize(stream);
stream.Close();
return user;
}
}

One file encryption for multiple public keys and private key decryption C#

I have ASP .NET C# project and I want to encrypt file with multiple public keys from certificates using X509Store and I am using this function to encrypt the file its fine but I need it for group of certificates:
private static void EncryptFile(string inFile, RSACryptoServiceProvider rsaPublicKey)
{
using (AesManaged aesManaged = new AesManaged())
{
// Create instance of AesManaged for
// symetric encryption of the data.
aesManaged.KeySize = 256;
aesManaged.BlockSize = 128;
aesManaged.Mode = CipherMode.CBC;
using (ICryptoTransform transform = aesManaged.CreateEncryptor())
{
RSAPKCS1KeyExchangeFormatter keyFormatter = new RSAPKCS1KeyExchangeFormatter(rsaPublicKey);
byte[] keyEncrypted = keyFormatter.CreateKeyExchange(aesManaged.Key, aesManaged.GetType());
// Create byte arrays to contain
// the length values of the key and IV.
byte[] LenK = new byte[4];
byte[] LenIV = new byte[4];
int lKey = keyEncrypted.Length;
LenK = BitConverter.GetBytes(lKey);
int lIV = aesManaged.IV.Length;
LenIV = BitConverter.GetBytes(lIV);
// Write the following to the FileStream
// for the encrypted file (outFs):
// - length of the key
// - length of the IV
// - ecrypted key
// - the IV
// - the encrypted cipher content
int startFileName = inFile.LastIndexOf("\\") + 1;
// Change the file's extension to ".enc"
string outFile = encrFolder + inFile.Substring(startFileName, inFile.LastIndexOf(".") - startFileName) + ".enc";
Directory.CreateDirectory(encrFolder);
using (FileStream outFs = new FileStream(outFile, FileMode.Create))
{
outFs.Write(LenK, 0, 4);
outFs.Write(LenIV, 0, 4);
outFs.Write(keyEncrypted, 0, lKey);
outFs.Write(aesManaged.IV, 0, lIV);
// Now write the cipher text using
// a CryptoStream for encrypting.
using (CryptoStream outStreamEncrypted = new CryptoStream(outFs, transform, CryptoStreamMode.Write))
{
// By encrypting a chunk at
// a time, you can save memory
// and accommodate large files.
int count = 0;
int offset = 0;
// blockSizeBytes can be any arbitrary size.
int blockSizeBytes = aesManaged.BlockSize / 8;
byte[] data = new byte[blockSizeBytes];
int bytesRead = 0;
using (FileStream inFs = new FileStream(inFile, FileMode.Open))
{
do
{
count = inFs.Read(data, 0, blockSizeBytes);
offset += count;
outStreamEncrypted.Write(data, 0, count);
bytesRead += blockSizeBytes;
}
while (count > 0);
inFs.Close();
}
outStreamEncrypted.FlushFinalBlock();
outStreamEncrypted.Close();
}
outFs.Close();
}
}
}
}

C# RijndaelManaged to Python equivalent

I have the following C# code (code is inherited and can't compile it). This is used to decrypt and unzip a saved file.
using System.Security.Cryptography;
using System.Text;
using ICSharpCode.SharpZipLib.Zip;
//Not the real key but same amount of chars
private const string kEncyptionKey = "01234567";
public string DecryptAndDecompressText (string strFileName)
{
// Decryption ///
FileStream fin = null;
try
{
fin = new FileStream(strFileName, FileMode.Open, FileAccess.Read);
}
catch (System.IO.FileNotFoundException)
{
return "";
}
MemoryStream memoryToDecompress = new MemoryStream();
UnicodeEncoding UE = new UnicodeEncoding();
RijndaelManaged RMCrypto = new RijndaelManaged();
// This is the encryption key for our file
byte[] key = UE.GetBytes(kEncyptionKey);
// Decrypt the data to a stream
CryptoStream cs = new CryptoStream( memoryToDecompress,
RMCrypto.CreateDecryptor(key, key),
CryptoStreamMode.Write);
byte [] fileBuffer = new byte[fin.Length];
fin.Read(fileBuffer, 0, fileBuffer.Length);
cs.Write(fileBuffer, 0, fileBuffer.Length);
fin.Close();
// Reset the index of the Memory Stream
memoryToDecompress.Position = 0;
// Let the GC clean this up, we still need the memory stream
//cs.Close();
// Decompress the File
ZipInputStream s;
s = new ZipInputStream(memoryToDecompress);
ZipEntry theEntry;
try
{
theEntry = s.GetNextEntry();
}
catch (System.Exception)
{
// Could not open the file...
return "";
}
}
I'm trying to create a python program to do the same. This is what I've got:
from Crypto.Cipher import AES
KEY = '01234567'.encode('utf-16be')
_f = open('<file>', 'r')
_content = _f.read()
_cipher = AES.new(KEY, AES.MODE_CBC, KEY)
_dcontent = _cipher.decrypt(_content)
with open('extract.zip', 'w') as newfile:
newfile.write(_dcontent)
_f.close()
I'm writing the result to the disk since I expect it to be a zip file (which contains one file). However I can't open the file with Archive Manager.
Any suggestions are welcome!
You have to use the same key. System.Text.UnicodeEncoding is the UTF-16le encoding which also has an equivalent in python:
KEY = '01234567'.encode('utf-16le')
You have to read and write the files in binary mode if you're on Windows:
_f = open('<file>', 'rb')
...
open('extract.zip', 'wb')
You should use the proper zip file library. I am guessing that is something format specific that is failing on your write statement. Using this library should avoid such drawbacks. The open function can take a password as optional in case it is protected.

Categories

Resources