Categories
Llibres Programació C# Javascript Hardware Fotografia Pelis Anglès Android Series Excursions Cites SQLServer Software HTML/CSS Politikon Estilogràfiques Tintes
Contacte: Àlex
|
Mantenibilitat del codi |
Vaig acumulant anys, i clar, codi antic. Codi que vaig fer jo, codi que van fer altres, però codi al fi i al cap. És com parlar llengües mortes, coses antigues i no tan antigues, inclús coses noves però que canvien les especificacions i s'han de modificar. Aquestes modificacions, ja sigui per millorar o per corregir les ha de fer algú, i últimament aquest algú sóc jo.
I m'adono del que al meu jo futur li molaria trobar per facilitar-me la vida.
- Mai, mai, mai, (potser no m'he expressat bé), mai, fer servir IF immediats, i menys aniuats. Es a dir això totalment prohibit:
var Servicer = filter.Servicer == GlobalConstant.DefaultId.ToString() || filter.Servicer.IsNullOrBlank()
? "" : filter.Servicer == GlobalConstant.ServicerNO
? String.Format(" AND (DEM.SERVICER = '{0}' OR DEM.SERVICER IS NULL)", filter.Servicer) : String.Format(" AND DEM.SERVICER = '{0}'", filter.Servicer);
En realitat, és una sola línia. A l'hora de depurar i veure per on va... mmmm... per on va? No hi ha cap premi a qui escrigui menys línies de codi.
- El tipus "var", a veure si un llenguatge és tipat, doncs fes-ho servir.
- Lambda expressions quilomètriques. Prohibides.
model.DatosVol.Where(x=>x.Value.VOL>0).ToList().ForEach(
x => x.Value.VOL_PCT = ((x.Value.VOL * 100)/
model.DatosVol.Where(y=>y.Value.Tipo_Calculo==x.Value.Tipo_Calculo
&& y.Value.Tipo_Contrato==(int)SLAsCliente_TipoContEnum.Global).Sum(y=>GetDividendo(y.Value.VOL))));
Ves i busca un bug, o corregeix algo de la forma de calcular-se... És la típica lluita entre funcionals vs procedurals, jo sóc procedural.
- Noms de funcions clars. A ser possible en un sol idioma. Res de dir funcions "TRACTAMENT" o "TRACTAMENT2". Si es pot incloure un comentari de que fa la funció ja és una gran millora.
I podria continuar, però això ja donaria per un altra post. I parlar del rendiment... perque veig que per millorar rendiment és més barat tirar de hardware i tancar els ulls. | #28/02/2022 17:39 Programació C# Autor: Alex Canalda
|
Downloader SFTP |
Quan per Nadal graven uns vídeos dels nens fent els pastorets i tens que compartir 3.5GB amb persones que tenen pocs coneixements d'informàtica a.k.a usuaris, i el tema pendrive no mola. No mola pel tema pandèmia i per que els usuaris són despistats i els pendrives no tornen.
Donat que tinc un servidor de SFTP a casa i que explicar com instal·lar i configurar un client de SFTP a segons qui doncs li pot donar un yuyu cerebral, o simplement no té temps ni ganes d'aprendre, cal fer algo fàcil de fer servir.
Doncs dit i fet, un programet dummy on hi ha un client de SFTP amb la configuració posada i el que ha de descarregar també. Ah! I com a bonus track donat que els usuaris van per Wifi, ara falla ara no, ara tenen una estona per descarregar, ara paren a descansar... Doncs té la funció "resume" o que continua allà on ho ha deixat.
El codi a continuació, és una aplicació Winforms de tota la vida, el formulari té dos botons, una barra de progrés i un quadre de text.
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Renci.SshNet;
using Renci.SshNet.Common;
using Renci.SshNet.Sftp;
namespace Downloader
{
public partial class frmDownloader : Form
{
bool EnMarxa = false;
public frmDownloader()
{
InitializeComponent();
}
private delegate void SetLogDelegate(string propertyValue);
public void SetLog(string propertyValue)
{
if (this.InvokeRequired)
{
this.Invoke(new SetLogDelegate(SetLog), propertyValue);
}
else
{
if (txtLog.Text.Length > 10000) txtLog.Text = "";
txtLog.Text += Environment.NewLine + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToLongTimeString() + " - " + propertyValue;
}
}
public string ObtenirIP(string host)
{
IPHostEntry hostEntry;
string adreca = "";
hostEntry = Dns.GetHostEntry(host);
if (hostEntry.AddressList.Length > 0)
{
IPAddress ip = hostEntry.AddressList[0];
adreca = ip.ToString();
}
return adreca;
}
private void btnDownload_Click(object sender, EventArgs e)
{
btnDownload.Enabled = false;
string host = @"sftp.elteudomini.aqui";
string username = "posaixo";
string password = @"aixoaltra";
string carpetaLocal;
List<clsCarpeta> CarpetesABaixar = new List<clsCarpeta>();
ConfiguracioABaixar(CarpetesABaixar);
string localDirectoryBase = AppDomain.CurrentDomain.BaseDirectory;
EnMarxa = true;
try
{
SetLog("Intentant conectar: " + host + " - " + ObtenirIP(host));
using (SftpClient client = new SftpClient(host, username, password))
{
try
{
client.Connect();
}
catch (Exception Ex)
{
SetLog("Error conectant: " + Ex.Message);
}
if (!client.IsConnected)
{
SetLog("Client no ha conectat");
return;
}
else
{
SetLog("Conectat OK");
}
foreach (clsCarpeta Carpeta in CarpetesABaixar)
{
carpetaLocal = localDirectoryBase + Carpeta.NomLocal;
if (!Directory.Exists(carpetaLocal))
{
Directory.CreateDirectory(carpetaLocal);
}
foreach (clsFitxer Fitxer in Carpeta.Fitxers)
{
DescarregaFitxer(Fitxer, Carpeta, client);
}
}
}
}
catch(Exception Err)
{
SetLog("ERROR: " + Err.Message);
}
SetLog("Acabat");
btnDownload.Enabled = true;
}
private void DescarregaFitxer(clsFitxer fitxer, clsCarpeta carpeta, SftpClient client)
{
int numIntents = 0;
int maxIntents = 10;
bool retry = false;
float percentatgeFet = 0;
string localDirectory = AppDomain.CurrentDomain.BaseDirectory + carpeta.NomLocal;
string NomSencerFitxerRemot = carpeta.NomRemot + fitxer.Nom;
do
{
bool retrying = retry;
retry = false;
if (!client.Exists(NomSencerFitxerRemot))
{
SetLog("Fitxer remot no trobat: " + NomSencerFitxerRemot);
return;
}
SetLog("Obtenint atributs del fitxer: " + NomSencerFitxerRemot);
SftpFileAttributes atributs = client.GetAttributes(NomSencerFitxerRemot);
long MidaTotal = atributs.Size;
fitxer.Mida = MidaTotal;
SetLog("Mida del fitxer a descarregar: " + MidaTotal);
string destinationFile = Path.Combine(localDirectory, fitxer.Nom);
SetLog("Grabant fitxer a: " + destinationFile);
if (File.Exists(destinationFile))
{
FileInfo infoFitxerLocal = new FileInfo(destinationFile);
if (infoFitxerLocal.Length == fitxer.Mida)
{
SetLog("Fitxer " + fitxer.Nom + " ja descarregat, saltant al següent");
return;
}
else
{
retrying = true;
}
}
try
{
Stream destinationStream;
try
{
if (retrying)
{
SetLog("Continuant descarrega");
destinationStream = new FileStream(destinationFile, FileMode.Append);
}
else
{
SetLog("Descarrega nova de cero");
destinationStream = new FileStream(destinationFile, FileMode.Create);
}
}
catch (Exception Err)
{
SetLog("No s'ha pogut crear el fitxer local: " + destinationFile);
SetLog(Err.Message);
return;
}
using (destinationStream)
using (SftpFileStream sourceStream = client.Open(NomSencerFitxerRemot, FileMode.Open))
{
sourceStream.Seek(destinationStream.Length, SeekOrigin.Begin);
byte[] buffer = new byte[81920];
int read;
long total = destinationStream.Length;
while ((read = sourceStream.Read(buffer, 0, buffer.Length)) != 0)
{
destinationStream.Write(buffer, 0, read);
total = total + (long)read;
percentatgeFet = ((float)total / (float)MidaTotal) * 100;
prgBarDescarregat.Value = (int)Math.Truncate(percentatgeFet);
lblProgress.Text = Math.Round(percentatgeFet, 2) + "%";
Application.DoEvents();
if (!EnMarxa)
{
client.Disconnect();
return;
}
}
}
}
catch (SshException ex)
{
SetLog("Error: " + ex.Message);
retry = true;
numIntents++;
SetLog("Reintents: " + numIntents);
if (numIntents > maxIntents)
{
SetLog("Sortint per mases reintents: " + numIntents);
break;
}
}
}
while (retry);
}
private void ConfiguracioABaixar(List<clsCarpeta> carpetesABaixar)
{
clsCarpeta Carpeta;
clsFitxer Fitxer;
Carpeta = new clsCarpeta();
Carpeta.NomLocal = "Harry Potter";
Carpeta.NomRemot = "/Incoming2/Pelis infantils/Harry Potter/";
Fitxer = new clsFitxer();
Fitxer.Nom = "bla bla bla 1.mkv";
Carpeta.Fitxers.Add(Fitxer);
Fitxer = new clsFitxer();
Fitxer.Nom = "Bla bla bla 2.mkv";
Carpeta.Fitxers.Add(Fitxer);
carpetesABaixar.Add(Carpeta);
}
private void btnTancar_Click(object sender, EventArgs e)
{
EnMarxa = false;
Application.Exit();
}
}
}
| #19/04/2021 19:50 C# Software Autor: Alex Canalda
|
C# - com obrir un fitxer de text sense obtenir caracters estranys |
Seguim amb els petits detalls, res gaire complicat, però que molesten. Quan obres un fitxer de text a vegades té caràcters estranys en els accents quan llegeixes les línies. Normalment és la codificació. Per això cal posar-ho en la funció que fa la lectura.
StreamReader reader = new StreamReader(NombreFichero, Encoding.GetEncoding("iso-8859-1"))
| #02/10/2020 15:55 Programació C# Autor: Alex Canalda
|
C# - com ensenyar el format espanyol de la data |
Sempre em despito i mai recordo el format... Ainsss, deu ser l'edat.
DateTime.Now.ToString("dd'/'MM'/'yyyy HH:mm:ss");
| #02/10/2020 15:52 Programació C# Autor: Alex Canalda
|
Firma AES CMAC - RFC 4493 |
El 3DES ja va quedant enrera i ara cal una nova firma. Clar, ha d'estar basada en el successor del 3DES, el AES. Per això m'ha tocat implementar la firma AES CMAC - RFC 4493 i ho he fet en C#. I de dues formes diferents. Primer fent els passos individuals segons l'especificació, i de la manera comodona: fent servir la llibreria BouncyCastle. Primer fent-ho a màs, pas a pas. La dificultat està en la generació d'una sub-clau, que per això he posat un comentari amb l'especificació de com fer-ho del RFC:
byte[] AESEncrypt(byte[] key, byte[] iv, byte[] data)
{
using (MemoryStream ms = new MemoryStream())
{
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.None;
using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
cs.Write(data, 0, data.Length);
cs.FlushFinalBlock();
return ms.ToArray();
}
}
}
byte[] Rol(byte[] b)
{
byte[] r = new byte[b.Length];
byte carry = 0;
for (int i = b.Length - 1; i >= 0; i--)
{
ushort u = (ushort)(b[i] << 1);
r[i] = (byte)((u & 0xff) + carry);
carry = (byte)((u & 0xff00) >> 8);
}
return r;
}
byte[] AESCMAC(byte[] key, byte[] data)
{
byte[] L = AESEncrypt(key, new byte[16], new byte[16]);
byte[] FirstSubkey = Rol(L);
if ((L[0] & 0x80) == 0x80)
FirstSubkey[15] ^= 0x87;
byte[] SecondSubkey = Rol(FirstSubkey);
if ((FirstSubkey[0] & 0x80) == 0x80)
SecondSubkey[15] ^= 0x87;
if (((data.Length != 0) && (data.Length % 16 == 0)) == true)
{
for (int j = 0; j < FirstSubkey.Length; j++)
data[data.Length - 16 + j] ^= FirstSubkey[j];
}
else
{
data = AddPaddingAES(data);
for (int j = 0; j < 16; j++) data[data.Length - 16 + j] ^= SecondSubkey[j];
}
byte[] encResult = AESEncrypt(key, new byte[16], data);
byte[] HashValue = new byte[16];
Array.Copy(encResult, encResult.Length - HashValue.Length, HashValue, 0, HashValue.Length);
return HashValue;
}
I tot això que sembla tan complicat... només són unes poques linies fent servir BouncyCastle. Però ja es sap... la veritat està en el codi, i amb la llibreria no els veus. I el curiós és que ambdues versions donen el mateix resultat:
Org.BouncyCastle.Crypto.Engines.AesEngine aes = new Org.BouncyCastle.Crypto.Engines.AesEngine();
Org.BouncyCastle.Crypto.Macs.CMac cMac = new Org.BouncyCastle.Crypto.Macs.CMac(aes, 64);
Org.BouncyCastle.Crypto.Parameters.KeyParameter kp = new Org.BouncyCastle.Crypto.Parameters.KeyParameter(key);
cMac.Init(kp);
int MacLenght = cMac.GetMacSize();
byte[] output = new byte[MacLenght];
cMac.BlockUpdate(data, 0, data.Length);
cMac.DoFinal(output, 0);
txtBase64.Text = ConvertByteArrayToHexString(output);
Hi ha un conjunt de proves disponibles a un RFC.
I ja està, una altra firma feta. | #23/01/2020 17:00 Programació C# Autor: Alex Canalda
|
Xifrant fitxers en AES |
El petit hashejador que va creixer ha crescut un xic més. Ara ja incorpora xifrat.
I clar, el xifrat ha de ser simètric per anar ràpid. El 3DES ja l'estan treient de circulació, encara no està retirat però ja es considera un xifrat dèbil. El que s'està aplicant ara és el AES, encara que l'AES és del 1998 i el 3DES del 1995... gaire moderns no són.
Així que dit i fet ara he afegit les opcions de xifrat:
- "obre" desxifra una carpeta, elimina els fitxers xifrats i deixa els normals.
- "tanca" xifra una carpeta, elimina els fitxers normals i deixa els xifrats.
- "-pxxxx" i a continuació la contrasenya feta servir per xifrar o desxifrar.
- "[-f]" force, salta les precaucions: No xifrar dos cops, verificar la contrasenya.
- "[-r]" Recursiu, per aplicar la mateixa operació a les subcarpetes.
- "-cnom_carpeta" nom de la carpeta a processar. Si no informat es fa servir carpeta executable.
- "neteja" esborra el fitxer locker.xml, amb opcio [-r]
- "crea -cnom_carpeta [-r] [-desde_cero]" crea un fitxer XML amb els Hash dels fitxers. -r indica recursiu. -desde_cero: esborra els fitxers de hashos existents.
- "verifica -cnom_carpeta [-r] [-continua]" verifica que els fitxers tinguin el Hash correcte, -r indica recursiu, -continua no verifica els fitxers en estat VERIFICAT
- "resultats -cnom_carpeta [-r]" no calcula hashos, llegeix els fitxers del hasher buscant fitxers amb modificacions, -r indica recursiu
- "actualitza -cpath [-r]" calcula hashos per fitxers nous, esborra del fitxer de hashos els que pertanyen a fitxers esborrats, -r indica recursiu
- "reset -cpath [-r]" reseteja l'estat a PENDENT, -r indica recursiu
- "crea_tanca" realitza dues accions seguides.
- "verifica_tanca" realitza dues accions seguides.
- "obre_verifica" realitza dues accions seguides.
- El fitxer locker.xml conté informació sobre el tancat.
- El fitxer hasher.xml conté informació sobre els hashos, l'estat del fitxer i la data que es va fer.
Com sempre el codi a continuació:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace OpenSesame
{
class Program
{
private static string ExecutablePath = "";
private static string Accio = "";
private static bool Recursiu = false;
private static bool Force = false;
private static string Pwd = "";
private static string CarpetaAProcessar = "";
private static bool Creacio_de_cero = false;
private static bool Continua = false;
static void Main(string[] args)
{
string AppPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
ExecutablePath = Path.GetDirectoryName(AppPath);
clsDadesDesxifratRetorn ResultatsDesxifrar = null;
clsDadesVerificacioRetorn ResultatsVerificacio = null;
clsDadesXifratRetorn ResultatsXifrat = null;
try
{
ParseParams(args);
if (string.IsNullOrWhiteSpace(CarpetaAProcessar)) CarpetaAProcessar = ExecutablePath;
switch (Accio)
{
case "obre":
if (string.IsNullOrWhiteSpace(Pwd))
{
Console.WriteLine("Password no informada");
return;
}
ResultatsDesxifrar = obre(CarpetaAProcessar);
Console.WriteLine(ResultatsDesxifrar.AString());
break;
case "tanca":
if (string.IsNullOrWhiteSpace(Pwd))
{
Console.WriteLine("Password no informada");
return;
}
ResultatsXifrat = tanca(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - xifrat acabat.");
Console.WriteLine(ResultatsXifrat.AString());
break;
case "neteja":
Neteja(CarpetaAProcessar);
break;
case "crea":
crea(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - creació acabada.");
break;
case "verifica":
ResultatsVerificacio = verifica(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - verificació acabada.");
Console.WriteLine(ResultatsVerificacio.AString());
break;
case "resultats":
ResultatsVerificacio = resultats(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - resultats acabat");
Console.WriteLine(ResultatsVerificacio.AString());
break;
case "actualitza":
actualitza(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - actualitza acabat.");
break;
case "reset":
reset(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - reset acabat.");
break;
case "crea_tanca":
crea(CarpetaAProcessar);
ResultatsXifrat = tanca(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - crea_tanca acabat.");
Console.WriteLine(ResultatsXifrat.AString());
break;
case "verifica_tanca":
ResultatsVerificacio = verifica(CarpetaAProcessar);
if (ResultatsVerificacio.FitxersHashDiferent == 0)
{
ResultatsXifrat = tanca(CarpetaAProcessar);
}
else
{
Console.WriteLine(ObtenirData() + " - xifrat no efectuat, hi ha fitxers amb hashs diferents dels esperats.");
Console.WriteLine("Actualitzar els hashos o fer servir l'opció \"tanca\" de forma individual");
ResultatsXifrat = new clsDadesXifratRetorn();
}
Console.WriteLine(ObtenirData() + " - resultats verificació:");
Console.Write(ResultatsVerificacio.AString());
Console.WriteLine(ObtenirData() + " - resultats xifrat:");
Console.Write(ResultatsXifrat.AString());
break;
case "obre_verifica":
ResultatsDesxifrar = obre(CarpetaAProcessar);
ResultatsVerificacio = verifica(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - resultats desxifrar:");
Console.Write(ResultatsDesxifrar.AString());
Console.WriteLine(ObtenirData() + " - resultats verificació:");
Console.Write(ResultatsVerificacio.AString());
break;
default:
Console.WriteLine("Possibles accions:");
Console.WriteLine("\"obre\" desxifra una carpeta, elimina els fitxers xifrats i deixa els normals.");
Console.WriteLine("\"tanca\" xifra una carpeta, elimina els fitxers normals i deixa els xifrats.");
Console.WriteLine("\"-pxxxx\" i a continuació la contrasenya feta servir per xifrar o desxifrar.");
Console.WriteLine("[-f] force, salta les precaucions: No xifrar dos cops, verificar la contrasenya.");
Console.WriteLine("[-r] Recursiu, per aplicar la mateixa operació a les subcarpetes.");
Console.WriteLine("\"-cnom_carpeta\" nom de la carpeta a processar. Si no informat es fa servir carpeta executable.");
Console.WriteLine("\"neteja\" esborra el fitxer hasher.xml i locker.xml, amb opcio [-r]");
Console.WriteLine("\"crea -cnom_carpeta [-r] [-desde_cero]\" crea un fitxer XML amb els Hash dels fitxers. -r indica recursiu. -desde_cero: esborra els fitxers de hashos existents.");
Console.WriteLine("\"verifica -cnom_carpeta [-r] [-continua]\" verifica que els fitxers tinguin el Hash correcte, -r indica recursiu, -continua no verifica els fitxers en estat VERIFICAT");
Console.WriteLine("\"resultats -cnom_carpeta [-r]\" no calcula hashos, llegeix els fitxers del hasher buscant fitxers amb modificacions, -r indica recursiu");
Console.WriteLine("\"actualitza -cpath [-r]\" calcula hashos per fitxers nous, esborra del fitxer de hashos els que pertanyen a fitxers esborrats, -r indica recursiu");
Console.WriteLine("\"reset -cpath [-r]\" reseteja l'estat a PENDENT, -r indica recursiu");
Console.WriteLine("\"crea_tanca\" realitza dues accions seguides.");
Console.WriteLine("\"verifica_tanca\" realitza dues accions seguides.");
Console.WriteLine("\"obre_verifica\" realitza dues accions seguides.");
Console.WriteLine("El fitxer locker.xml conté informació sobre el tancat.");
Console.WriteLine("El fitxer hasher.xml conté informació sobre els hashos, l'estat del fitxer i la data que es va fer.");
break;
}
Console.WriteLine("OpenSesame 1.0 - 03-03-2020");
}
catch(Exception Err)
{
Console.WriteLine(Err.Message);
}
}
private static void reset(string pPath)
{
if (!File.Exists(pPath + "\\hasher.xml"))
{
Console.WriteLine(ObtenirData() + " - No hi ha fitxer de hashos: " + pPath);
}
else
{
Dictionary<string, clsFitxer> DicFitxers;
DicFitxers = CarregaHashos(pPath);
Console.WriteLine(ObtenirData() + " - resetejant: " + pPath);
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
objFitxer.Value.Estat = "PENDENT";
}
Save(pPath, DicFitxers);
}
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
reset(Carpeta);
}
}
}
private static void Neteja(string pPath)
{
if (!Directory.Exists(pPath))
{
Console.WriteLine("Carpeta no trobada: " + pPath);
}
else
{
if (File.Exists(pPath + "\\locker.xml"))
{
File.Delete(pPath + "\\locker.xml");
}
if (File.Exists(pPath + "\\hasher.xml"))
{
File.Delete(pPath + "\\hasher.xml");
}
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
Neteja(Carpeta);
}
}
}
}
private static void ParseParams(string[] args)
{
for (int i = 0; i < args.Length; i++)
{
if (args[i].ToLower() == "obre")
{
Accio = "obre";
}
if (args[i].ToLower() == "tanca")
{
Accio = "tanca";
}
if (args[i].ToLower() == "neteja")
{
Accio = "neteja";
}
if (args[i].ToLower().StartsWith("-p"))
{
Pwd = args[i].Replace("-p", "");
}
if (args[i].ToLower() == "crea")
{
Accio = "crea";
}
if (args[i].ToLower() == "verifica")
{
Accio = "verifica";
}
if (args[i].ToLower() == "resultats")
{
Accio = "resultats";
}
if (args[i].ToLower() == "actualitza")
{
Accio = "actualitza";
}
if (args[i].ToLower() == "reset")
{
Accio = "reset";
}
if (args[i].ToLower() == "crea_tanca")
{
Accio = "crea_tanca";
}
if (args[i].ToLower() == "verifica_tanca")
{
Accio = "verifica_tanca";
}
if (args[i].ToLower() == "obre_verifica")
{
Accio = "obre_verifica";
}
if (args[i].ToLower() == "-r")
{
Recursiu = true;
}
if (args[i].ToLower() == "-desde_cero")
{
Creacio_de_cero = true;
}
if (args[i].ToLower() == "-continua")
{
Continua = true;
}
if (args[i].ToLower() == "-f")
{
Force = true;
}
if (args[i].Contains(":") && args[i].Contains("-c"))
{
CarpetaAProcessar = args[i].Replace("\\\\", "\\").Replace("-c", "").Trim();
}
}
}
private static byte[] PwdBytes(string pPwd)
{
SHA256Managed SHA2 = new SHA256Managed();
UTF8Encoding encoder = new UTF8Encoding();
byte[] bodyStringBytes = encoder.GetBytes(pPwd);
byte[] pwdBytes = SHA2.ComputeHash(bodyStringBytes);
return pwdBytes;
}
private static byte[] IVBytes(string pPwd, string FileName)
{
SHA256Managed SHA2 = new SHA256Managed();
UTF8Encoding encoder = new UTF8Encoding();
byte[] bodyStringBytes = encoder.GetBytes(pPwd + FileName);
byte[] IV = new byte[16];
byte[] Hash = SHA2.ComputeHash(bodyStringBytes);
int i, j;
i = 0;
j = 0;
while (i < 32)
{
IV[j] = Hash[i];
i = i + 2;
j++;
}
return IV;
}
private static clsDadesDesxifratRetorn obre(string pPath)
{
string[] Fitxers = Directory.GetFiles(pPath, "*.xxx");
byte[] passwordBytes = PwdBytes(Pwd);
clsConfig Config = new clsConfig();
string KCVPwd = CalcularKCV();
string KCVFitxer = "";
bool ErrorDesxifrant = false;
clsDadesDesxifratRetorn Retorn = new clsDadesDesxifratRetorn();
if (!Directory.Exists(pPath))
{
Console.WriteLine("Carpeta no trobada: " + pPath);
return Retorn;
}
DirectoryInfo DInfo = new DirectoryInfo(pPath);
if (DInfo.Attributes.HasFlag(FileAttributes.Hidden))
{
Console.WriteLine(ObtenirData() + " - carpeta oculta no processada: " + pPath);
return Retorn;
}
Config.Initialize(pPath);
if (Config.bError && !Force)
{
Console.WriteLine(ObtenirData() + " - Sense config: " + Config.txtError + ". Fer servir opció -f (force).");
Retorn.CarpetesSenseFitxerConfiguracio++;
}
else
{
if (Config.GetVal("Estat") == "tancat" || Force )
{
KCVFitxer = Config.GetVal("ValidadorClau");
if (KCVFitxer == KCVPwd || Force)
{
if (Fitxers.Length != 0)
{
foreach (string Fitxer in Fitxers)
{
if (PotProcessarFitxer(Fitxer))
{
FileInfo FInfo = new FileInfo(Fitxer);
ErrorDesxifrant = false;
try
{
DeCryptFile(Fitxer, passwordBytes, FInfo.Length);
Console.WriteLine(ObtenirData() + " - DeCrypted OK: " + Path.GetFileName(Fitxer));
Retorn.FitxersDesxifratsOK++;
}
catch(Exception Err)
{
Console.WriteLine(ObtenirData() + " - Error desxifrant: " + Fitxer);
Console.WriteLine(Err.Message);
Retorn.FitxersDesxifratsKO++;
ErrorDesxifrant = true;
}
try
{
if (!ErrorDesxifrant)
{
File.Delete(Fitxer);
Retorn.FitxersEsborratsOK++;
}
}
catch (Exception Err)
{
Console.WriteLine(ObtenirData() + " - Error esborrant fitxer: " + Path.GetFileName(Fitxer) + ", " + Err.Message);
Retorn.FitxersEsborratsKO++;
}
}
}
}
else
{
Console.WriteLine(ObtenirData() + " - No hi ha fitxers a obrir: " + pPath);
Retorn.CarpetesSenseFitxers++;
}
Config.SetVal("Estat", "obert");
Config.SetVal("Data", DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());
Config.Save(pPath);
}
else
{
Console.WriteLine(ObtenirData() + " - Password incorrecte: " + pPath);
Retorn.CarpetesPwdIncorrecte++;
}
}
else
{
Console.WriteLine(ObtenirData() + " - La carpeta ja està oberta: " + pPath);
Retorn.CarpetesJaDesxifrades++;
}
}
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
clsDadesDesxifratRetorn RetornRecusiu;
foreach (string Carpeta in Carpetes)
{
RetornRecusiu = obre(Carpeta);
Retorn.CarpetesJaDesxifrades = Retorn.CarpetesJaDesxifrades + RetornRecusiu.CarpetesJaDesxifrades;
Retorn.CarpetesPwdIncorrecte = Retorn.CarpetesPwdIncorrecte + RetornRecusiu.CarpetesPwdIncorrecte;
Retorn.CarpetesSenseFitxerConfiguracio = Retorn.CarpetesSenseFitxerConfiguracio + RetornRecusiu.CarpetesSenseFitxerConfiguracio;
Retorn.CarpetesSenseFitxers = Retorn.CarpetesSenseFitxers + RetornRecusiu.CarpetesSenseFitxers;
Retorn.FitxersDesxifratsKO = Retorn.FitxersDesxifratsKO + RetornRecusiu.FitxersDesxifratsKO;
Retorn.FitxersDesxifratsOK = Retorn.FitxersDesxifratsOK + RetornRecusiu.FitxersDesxifratsOK;
Retorn.FitxersEsborratsKO = Retorn.FitxersEsborratsKO + RetornRecusiu.FitxersEsborratsKO;
Retorn.FitxersEsborratsOK = Retorn.FitxersEsborratsOK + RetornRecusiu.FitxersEsborratsOK;
}
}
return Retorn;
}
private static clsDadesXifratRetorn tanca(string pPath)
{
clsDadesXifratRetorn Retorn = new clsDadesXifratRetorn();
string[] Fitxers = Directory.GetFiles(pPath);
byte[] passwordBytes = PwdBytes(Pwd);
bool ErrorXifrant = false;
clsConfig Config = new clsConfig();
long TamanyFitxer = 0;
if (!Directory.Exists(pPath))
{
Console.WriteLine("Carpeta no trobada: " + pPath);
return Retorn;
}
DirectoryInfo DInfo = new DirectoryInfo(pPath);
if (DInfo.Attributes.HasFlag(FileAttributes.Hidden))
{
Console.WriteLine(ObtenirData() + " - carpeta oculta no processada: " + pPath);
return Retorn;
}
if (File.Exists(pPath + "\\locker.xml"))
{
Config.Initialize(pPath);
}
else
{
Retorn.CarpetesSenseFitxerConfiguracio++;
Console.WriteLine(ObtenirData() + " - carpeta sense fitxer de configuració.");
}
if(Config.GetVal("Estat") == "tancat")
{
Retorn.CarpetesJaXifrades++;
Console.WriteLine(ObtenirData() + " - carpeta ja tancada, si vols tancar-la altra cop, esborra el fitxer locker.xml");
return Retorn;
}
Config.SetVal("ValidadorClau", CalcularKCV());
Config.SetVal("Estat", "tancat");
Config.SetVal("Data", DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());
foreach (string Fitxer in Fitxers)
{
if (PotProcessarFitxer(Fitxer.ToLower()))
{
ErrorXifrant = false;
FileInfo FInfo = new FileInfo(Fitxer);
if (FInfo.IsReadOnly)
{
Retorn.FitxersReadonly++;
Console.WriteLine(ObtenirData() + " - fitxer readonly no xifrat: " + Path.GetFileName(Fitxer));
}
else
{
TamanyFitxer = FInfo.Length;
if (TamanyFitxer == 0)
{
Retorn.FitxersTamany0++;
Console.WriteLine(ObtenirData() + " - fitxer tamany 0 no xifrat: " + Path.GetFileName(Fitxer));
}
else
{
if (FInfo.Attributes.HasFlag(FileAttributes.Hidden))
{
Retorn.FitxersOcults++;
Console.WriteLine(ObtenirData() + " - fitxer ocult no xifrat: " + Path.GetFileName(Fitxer));
}
else
{
try
{
CryptFile(Fitxer, passwordBytes, TamanyFitxer);
Retorn.FitxersXifratsOK++;
}
catch (Exception Err)
{
ErrorXifrant = true;
Console.WriteLine(ObtenirData() + " - error xifrant fitxer: " + Path.GetFileName(Fitxer) + ": " + Err.Message);
Retorn.FitxersXifratsKO++;
}
try
{
if (!ErrorXifrant)
{
File.Delete(Fitxer);
Retorn.FitxersEsborratsOK++;
}
}
catch (Exception Err)
{
Retorn.FitxersEsborratsKO++;
Console.WriteLine(ObtenirData() + " - error esborrant fitxer: " + Path.GetFileName(Fitxer) + ", " + Err.Message);
}
}
}
}
}
}
Config.Save(pPath);
if (Recursiu)
{
clsDadesXifratRetorn RetornRecursiu = null;
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
RetornRecursiu = tanca(Carpeta);
Retorn.CarpetesJaXifrades = Retorn.CarpetesJaXifrades + RetornRecursiu.CarpetesJaXifrades;
Retorn.CarpetesSenseFitxerConfiguracio = Retorn.CarpetesSenseFitxerConfiguracio + RetornRecursiu.CarpetesSenseFitxerConfiguracio;
Retorn.FitxersEsborratsKO = Retorn.FitxersEsborratsKO + RetornRecursiu.FitxersEsborratsKO;
Retorn.FitxersEsborratsOK = Retorn.FitxersEsborratsOK + RetornRecursiu.FitxersEsborratsOK;
Retorn.FitxersOcults = Retorn.FitxersOcults + RetornRecursiu.FitxersOcults;
Retorn.FitxersReadonly = Retorn.FitxersReadonly + RetornRecursiu.FitxersReadonly;
Retorn.FitxersTamany0 = Retorn.FitxersTamany0 + RetornRecursiu.FitxersTamany0;
Retorn.FitxersXifratsKO = Retorn.FitxersXifratsKO + RetornRecursiu.FitxersXifratsKO;
Retorn.FitxersXifratsOK = Retorn.FitxersXifratsOK + RetornRecursiu.FitxersXifratsOK;
}
}
return Retorn;
}
private static bool PotProcessarFitxer(string Fitxer)
{
string NomEnMinuscules = Fitxer.ToLower();
if (!NomEnMinuscules.Contains("opensesame.exe")
&& !NomEnMinuscules.Contains("hasher.xml")
&& !NomEnMinuscules.Contains("hasher.exe")
&& !NomEnMinuscules.Contains("locker.xml"))
{
return true;
}
else
{
return false;
}
}
private static void CryptFile(string inputFile, byte[] passwordBytes, long TamanyFitxer)
{
FileStream fsCrypt = new FileStream(inputFile + ".xxx", FileMode.Create);
string NomFitxerSenseRutaNiUnitat = Path.GetFileName(inputFile);
RijndaelManaged AES = new RijndaelManaged();
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Padding = PaddingMode.PKCS7;
AES.Key = passwordBytes;
NomFitxerSenseRutaNiUnitat = NomFitxerSenseRutaNiUnitat.ToLower();
AES.IV = IVBytes(Pwd, NomFitxerSenseRutaNiUnitat);
AES.FeedbackSize = 128;
AES.Mode = CipherMode.CFB;
CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write);
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
byte[] buffer = new byte[4194304];
int read;
if (TamanyFitxer < 4194304)
{
while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)
{
cs.Write(buffer, 0, read);
}
Console.WriteLine(ObtenirData() + " - crypted OK: " + Path.GetFileName(inputFile));
}
else
{
double Percentatge = 0;
string strPercentatge = "";
while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)
{
Percentatge = (double) fsIn.Position / TamanyFitxer;
Percentatge = Percentatge * 100;
Percentatge = Math.Round(Percentatge, 2);
strPercentatge = String.Format("{0:00.00}", Percentatge);
Console.Write("\r" + ObtenirData(DateTime.Now) + " - crypted " + strPercentatge + "% " + Path.GetFileName(inputFile));
cs.Write(buffer, 0, read);
}
Console.WriteLine();
}
fsIn.Close();
cs.Close();
fsCrypt.Close();
}
private static void DeCryptFile(string inputFile, byte[] passwordBytes, long TamanyFitxer)
{
string NomFitxerSenseRutaNiUnitat = Path.GetFileName(inputFile);
NomFitxerSenseRutaNiUnitat = NomFitxerSenseRutaNiUnitat.Replace(".xxx", "");
NomFitxerSenseRutaNiUnitat = NomFitxerSenseRutaNiUnitat.ToLower();
FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);
RijndaelManaged AES = new RijndaelManaged();
AES.KeySize = 256;
AES.BlockSize = 128;
AES.FeedbackSize = 128;
AES.Key = passwordBytes;
AES.IV = IVBytes(Pwd, NomFitxerSenseRutaNiUnitat);
AES.Padding = PaddingMode.PKCS7;
AES.Mode = CipherMode.CFB;
CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateDecryptor(), CryptoStreamMode.Read);
FileStream fsOut = new FileStream(inputFile.Replace(".xxx", ""), FileMode.Create);
int read;
byte[] buffer = new byte[4194304];
if (TamanyFitxer < 4194304)
{
while ((read = cs.Read(buffer, 0, buffer.Length)) > 0)
{
fsOut.Write(buffer, 0, read);
}
}
else
{
long Posicio = 0;
double Percentatge = 0;
string strPercentatge = "";
while ((read = cs.Read(buffer, 0, buffer.Length)) > 0)
{
Posicio = Posicio + read;
Percentatge = (double) Posicio / TamanyFitxer;
Percentatge = Percentatge * 100;
Percentatge = Math.Round(Percentatge, 2);
strPercentatge = String.Format("{0:00.00}", Percentatge);
Console.Write("\r" + ObtenirData(DateTime.Now) + " - Decrypted " + strPercentatge + "% " + Path.GetFileName(inputFile));
fsOut.Write(buffer, 0, read);
}
Console.WriteLine();
}
cs.Close();
fsOut.Close();
fsCrypt.Close();
}
private static string CalcularKCV()
{
try
{
AesCryptoServiceProvider AES = new AesCryptoServiceProvider();
#region definicio de variables
string strIVAES = "00000000000000000000000000000000";
byte[] IV = ConvertHexStringToByteArray(strIVAES);
byte[] OrigenBytes = null;
byte[] Encrypted = null;
byte[] KCV = new byte[3];
ICryptoTransform EncDec = null;
#endregion
AES.KeySize = 256;
AES.Key = PwdBytes(Pwd);
AES.IV = IV;
AES.Mode = CipherMode.ECB;
AES.Padding = PaddingMode.Zeros;
OrigenBytes = ConvertHexStringToByteArray("00000000000000000000000000000000");
Encrypted = new byte[OrigenBytes.Length];
EncDec = AES.CreateEncryptor();
EncDec.TransformBlock(OrigenBytes, 0, 16, Encrypted, 0);
KCV[0] = Encrypted[0];
KCV[1] = Encrypted[1];
KCV[2] = Encrypted[2];
return ConvertByteArrayToHexString(KCV);
}
catch (Exception E)
{
Console.WriteLine(E.Message);
return "ERROR";
}
}
public static string ConvertByteArrayToHexString(byte[] ba)
{
StringBuilder sb = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
{
sb.AppendFormat("{0:x2}", b);
}
return sb.ToString().ToUpper();
}
public static byte[] SubArray(byte[] data, int index, int length)
{
byte[] result = new byte[length];
Array.Copy(data, index, result, 0, length);
return result;
}
public static byte[] ConvertHexStringToByteArray(string hexString)
{
if (hexString.Length % 2 != 0)
{
throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "Los datos de entrada tiene un número impar de caracteres, no se puede convertir a Hexadecimal: {0}", hexString.Length));
}
byte[] HexAsBytes = new byte[hexString.Length / 2];
for (int index = 0; index < HexAsBytes.Length; index++)
{
string byteValue = hexString.Substring(index * 2, 2);
HexAsBytes[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
}
return HexAsBytes;
}
public static string ObtenirData()
{
return DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture);
}
public static string ObtenirData(DateTime data)
{
return data.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture);
}
public static string SHA256HashFile(string sPath)
{
string sHash = "";
using (var stream = new BufferedStream(File.OpenRead(sPath), 2400000))
{
SHA256CryptoServiceProvider sha256h = new SHA256CryptoServiceProvider();
sHash = BitConverter.ToString(sha256h.ComputeHash(stream));
}
return sHash;
}
private static void actualitza(string pPath)
{
if (!File.Exists(pPath + "\\hasher.xml"))
{
Console.WriteLine(ObtenirData() + " - No hi ha fitxer de hashos: " + pPath);
}
else
{
clsConfig Config = new clsConfig();
if (File.Exists(pPath + "\\locker.xml"))
{
Config.Initialize(pPath);
if (Config.GetVal("Estat") == "tancat")
{
Console.WriteLine("Carpeta xifrada, no es poden calcular els hashs dels fitxers");
return;
}
}
Dictionary<string, clsFitxer> DicFitxers;
Dictionary<string, clsFitxer> FitxersActualitzats = new Dictionary<string, clsFitxer>();
clsFitxer FitxerActualitzat = null;
DicFitxers = CarregaHashos(pPath);
DirectoryInfo dir = new DirectoryInfo(pPath);
FileInfo[] Fitxers = dir.GetFiles();
Console.WriteLine(ObtenirData() + " - Processant " + pPath);
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
try
{
if (File.Exists(pPath + "\\" + objFitxer.Value.Nom))
{
FitxerActualitzat = new clsFitxer(objFitxer.Value.Nom, objFitxer.Value.DataCreacio, objFitxer.Value.DataVerificacio, objFitxer.Value.MidaEnBytes, objFitxer.Value.Hash, objFitxer.Value.Estat);
FitxersActualitzats.Add(FitxerActualitzat.Nom, FitxerActualitzat);
}
}
catch (IOException e)
{
Console.WriteLine("I/O Exception: " + e.Message);
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("Access Exception: " + e.Message);
}
}
foreach (FileInfo Fitxer in Fitxers)
{
if (!DicFitxers.ContainsKey(Fitxer.Name))
{
if (PotProcessarFitxer(Fitxer.Name))
{
string hashValueStr = SHA256HashFile(Fitxer.FullName);
Console.WriteLine(ObtenirData() + " - hashejat: " + Fitxer.Name);
FitxerActualitzat = new clsFitxer(Fitxer.Name, DateTime.Now, DateTime.Now, Fitxer.Length, hashValueStr, "CREAT");
FitxersActualitzats.Add(Fitxer.Name, FitxerActualitzat);
}
}
}
Save(pPath, FitxersActualitzats);
}
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
actualitza(Carpeta);
}
}
}
public static void crea(string pPath)
{
bool Procesa_carpeta = false;
if (File.Exists(pPath + "\\hasher.xml"))
{
if (Creacio_de_cero)
{
File.Delete(pPath + "\\hasher.xml");
Console.WriteLine(ObtenirData() + " - Carpeta " + pPath + " amb fitxer de hashos, esborrat.");
Procesa_carpeta = true;
}
else
{
Console.WriteLine(ObtenirData() + " - Carpeta " + pPath + " amb fitxer de hashos, no procesada.");
Procesa_carpeta = false;
}
}
else
{
Procesa_carpeta = true;
}
if (Procesa_carpeta)
{
Console.WriteLine(ObtenirData() + " - creant fitxer hashos: " + pPath);
DirectoryInfo dir = new DirectoryInfo(pPath);
FileInfo[] files = dir.GetFiles();
clsFitxer objFitxer = null;
Dictionary<string, clsFitxer> DicFitxers = new Dictionary<string, clsFitxer>();
foreach (FileInfo Fitxer in files)
{
try
{
if (PotProcessarFitxer(Fitxer.Name))
{
string hashValueStr = SHA256HashFile(Fitxer.FullName);
Console.WriteLine(ObtenirData() + " - hashejat: " + Fitxer.Name);
objFitxer = new clsFitxer(Fitxer.Name, DateTime.Now, DateTime.Now, Fitxer.Length, hashValueStr, "CREAT");
DicFitxers.Add(Fitxer.Name, objFitxer);
}
}
catch (IOException e)
{
Console.WriteLine("I/O Exception: " + e.Message);
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("Access Exception: " + e.Message);
}
}
Save(pPath, DicFitxers);
}
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
crea(Carpeta);
}
}
}
public static void Save(string pPath, Dictionary<string, clsFitxer> DicFitxers)
{
XmlDocument Doc = new XmlDocument();
XmlNode Fitxers;
XmlNode Fitxer;
XmlNode Nom;
XmlNode Hash;
XmlNode DataCreacio;
XmlNode DataVerificacio;
XmlNode Estat;
XmlNode MidaEnBytes;
Doc.LoadXml("<?xml version=\"1.0\" standalone=\"yes\"?><fitxers></fitxers>");
Fitxers = Doc.SelectSingleNode("descendant::fitxers");
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
Fitxer = Doc.CreateNode(XmlNodeType.Element, "fitxer", "");
Nom = Doc.CreateNode(XmlNodeType.Element, "nom", "");
Hash = Doc.CreateNode(XmlNodeType.Element, "hash", "");
DataCreacio = Doc.CreateNode(XmlNodeType.Element, "datacreacio", "");
DataVerificacio = Doc.CreateNode(XmlNodeType.Element, "dataverificacio", "");
Estat = Doc.CreateNode(XmlNodeType.Element, "estat", "");
MidaEnBytes = Doc.CreateNode(XmlNodeType.Element, "midaenbytes", "");
Nom.InnerText = objFitxer.Value.Nom;
Hash.InnerText = objFitxer.Value.Hash;
DataCreacio.InnerText = ObtenirData(objFitxer.Value.DataCreacio);
DataVerificacio.InnerText = ObtenirData(objFitxer.Value.DataVerificacio);
Estat.InnerText = objFitxer.Value.Estat;
MidaEnBytes.InnerText = objFitxer.Value.MidaEnBytes.ToString();
Fitxer.AppendChild(Nom);
Fitxer.AppendChild(Hash);
Fitxer.AppendChild(DataCreacio);
Fitxer.AppendChild(DataVerificacio);
Fitxer.AppendChild(Estat);
Fitxer.AppendChild(MidaEnBytes);
Fitxers.AppendChild(Fitxer);
}
Doc.Save(pPath + "\\hasher.xml");
}
public static clsDadesVerificacioRetorn verifica(string pPath)
{
clsDadesVerificacioRetorn Retorn = new clsDadesVerificacioRetorn();
long GBHashejats = 0;
Console.WriteLine(ObtenirData() + " - verificant carpeta: " + pPath);
if (!File.Exists(pPath + "\\hasher.xml"))
{
Console.WriteLine(ObtenirData() + " - No hi ha fitxer de hashos: " + pPath);
}
else
{
clsConfig Config = new clsConfig();
if (File.Exists(pPath + "\\locker.xml"))
{
Config.Initialize(pPath);
if (Config.GetVal("Estat") == "tancat")
{
Console.WriteLine(ObtenirData() + " - Carpeta xifrada, no es poden verificar els hashs dels fitxers");
return Retorn;
}
}
Dictionary<string, clsFitxer> DicFitxers;
DicFitxers = CarregaHashos(pPath);
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
if (objFitxer.Value.Estat == "VERIFICAT" && Continua)
{
Console.WriteLine(ObtenirData() + " - fitxer ja verificat anteriorment: " + objFitxer.Value.Nom);
}
else
{
try
{
if (File.Exists(pPath + "\\" + objFitxer.Value.Nom))
{
FileInfo fiFitxer = new FileInfo(pPath + "\\" + objFitxer.Value.Nom);
if (fiFitxer.Length != objFitxer.Value.MidaEnBytes)
{
Retorn.FitxersMidaDiferent++;
Console.WriteLine(ObtenirData() + " - Fitxer amb mida diferent: " + fiFitxer.Name);
objFitxer.Value.Estat = "MIDA DIFERENT, actual: " + fiFitxer.Length;
}
else
{
GBHashejats += fiFitxer.Length;
string hashValueStr = SHA256HashFile(fiFitxer.FullName);
if (hashValueStr == objFitxer.Value.Hash)
{
Retorn.FitxersVerificats++;
Console.WriteLine(ObtenirData() + " - Fitxer verificat OK: " + fiFitxer.Name);
objFitxer.Value.Estat = "VERIFICAT";
}
else
{
Retorn.FitxersHashDiferent++;
Console.WriteLine(ObtenirData() + " - Fitxer amb hash canviat: " + fiFitxer.Name);
objFitxer.Value.Estat = "NO COINCIDEIX";
}
if (GBHashejats > 5368709120)
{
GBHashejats = 0;
Save(pPath, DicFitxers);
}
}
}
else
{
Retorn.FitxersEsborrats++;
Console.WriteLine(ObtenirData() + " - Fitxer esborrat: " + objFitxer.Value.Nom);
objFitxer.Value.Estat = "ESBORRAT";
}
objFitxer.Value.DataVerificacio = DateTime.Now;
}
catch (IOException e)
{
Console.WriteLine("I/O Exception: " + e.Message);
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("Access Exception: " + e.Message);
}
}
}
Save(pPath, DicFitxers);
}
if (Recursiu)
{
clsDadesVerificacioRetorn RetornRecursiu;
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
RetornRecursiu = verifica(Carpeta);
Retorn.FitxersVerificats = Retorn.FitxersVerificats + RetornRecursiu.FitxersVerificats;
Retorn.FitxersHashDiferent = Retorn.FitxersHashDiferent + RetornRecursiu.FitxersHashDiferent;
Retorn.FitxersMidaDiferent = Retorn.FitxersMidaDiferent + RetornRecursiu.FitxersMidaDiferent;
Retorn.FitxersEsborrats = Retorn.FitxersEsborrats + RetornRecursiu.FitxersEsborrats;
}
}
return Retorn;
}
private static clsDadesVerificacioRetorn resultats(string pPath)
{
clsDadesVerificacioRetorn Retorn = new clsDadesVerificacioRetorn();
if (!File.Exists(pPath + "\\hasher.xml"))
{
Console.WriteLine(ObtenirData() + " - No hi ha fitxer de hashos: " + pPath);
}
else
{
Dictionary<string, clsFitxer> DicFitxers;
DicFitxers = CarregaHashos(pPath);
Console.WriteLine(ObtenirData() + " - analitzant: " + pPath);
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
Retorn.FitxersVerificats++;
if (objFitxer.Value.Estat == "NO COINCIDEIX")
{
Retorn.FitxersHashDiferent++;
Console.WriteLine(ObtenirData(objFitxer.Value.DataVerificacio) + " - fitxer amb hash canviat: " + pPath + "\\" + objFitxer.Value.Nom);
}
else
{
if (objFitxer.Value.Estat.Contains("MIDA DIFERENT"))
{
Retorn.FitxersMidaDiferent++;
Console.WriteLine(ObtenirData(objFitxer.Value.DataVerificacio) + " - fitxer amb mida diferent: " + pPath + "\\" + objFitxer.Value.Nom);
}
else
{
if (objFitxer.Value.Estat == "ESBORRAT")
{
Retorn.FitxersEsborrats++;
Console.WriteLine(ObtenirData(objFitxer.Value.DataVerificacio) + " - fitxer esborrat: " + pPath + "\\" + objFitxer.Value.Nom);
}
}
}
}
}
if (Recursiu)
{
clsDadesVerificacioRetorn RetornRecursiu;
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
RetornRecursiu = resultats(Carpeta);
Retorn.FitxersVerificats = Retorn.FitxersVerificats + RetornRecursiu.FitxersVerificats;
Retorn.FitxersHashDiferent = Retorn.FitxersHashDiferent + RetornRecursiu.FitxersHashDiferent;
Retorn.FitxersMidaDiferent = Retorn.FitxersMidaDiferent + RetornRecursiu.FitxersMidaDiferent;
Retorn.FitxersEsborrats = Retorn.FitxersEsborrats + RetornRecursiu.FitxersEsborrats;
}
}
return Retorn;
}
public static Dictionary<string, clsFitxer> CarregaHashos(string pPath)
{
XmlDocument Doc = new XmlDocument();
XmlNode Fitxers;
XmlNodeList llistaDeFitxer;
XmlNode Nom;
XmlNode Hash;
XmlNode DataCreacio;
XmlNode DataVerificacio;
XmlNode Estat;
XmlNode MidaEnBytes;
clsFitxer objFitxer = null;
Dictionary<string, clsFitxer> DicFitxers = new Dictionary<string, clsFitxer>();
Doc.Load(pPath + "\\hasher.xml");
Fitxers = Doc.SelectSingleNode("descendant::fitxers");
llistaDeFitxer = Fitxers.ChildNodes;
foreach (XmlNode Fitxer in llistaDeFitxer)
{
objFitxer = new clsFitxer();
Nom = Fitxer.SelectSingleNode("descendant::nom");
Hash = Fitxer.SelectSingleNode("descendant::hash");
DataCreacio = Fitxer.SelectSingleNode("descendant::datacreacio");
DataVerificacio = Fitxer.SelectSingleNode("descendant::dataverificacio");
Estat = Fitxer.SelectSingleNode("descendant::estat");
MidaEnBytes = Fitxer.SelectSingleNode("descendant::midaenbytes");
if (Nom != null)
{
objFitxer.Nom = Nom.InnerText;
}
else
{
objFitxer.Nom = "Nom null";
}
if (Hash != null)
{
objFitxer.Hash = Hash.InnerText;
}
else
{
objFitxer.Hash = "Hash null";
}
if (DataCreacio != null)
{
objFitxer.DataCreacio = DateTime.ParseExact(DataCreacio.InnerText, "dd/MM/yyyy HH:mm:ss", null);
}
else
{
objFitxer.DataCreacio = DateTime.Now;
}
if(DataVerificacio != null)
{
objFitxer.DataVerificacio = DateTime.ParseExact(DataVerificacio.InnerText, "dd/MM/yyyy HH:mm:ss", null);
}
else
{
objFitxer.DataVerificacio = DateTime.Now;
}
if(Estat != null)
{
objFitxer.Estat = Estat.InnerText;
}
else
{
objFitxer.Estat = "Estat null";
}
if(MidaEnBytes != null)
{
objFitxer.MidaEnBytes = long.Parse(MidaEnBytes.InnerText);
}
else
{
objFitxer.MidaEnBytes = 0;
}
DicFitxers.Add(objFitxer.Nom, objFitxer);
}
return DicFitxers;
}
}
}
I classes de retorn que es dediquen a recollir estadístiques:
class clsDadesDesxifratRetorn
{
public int FitxersDesxifratsOK = 0;
public int FitxersDesxifratsKO = 0;
public int FitxersEsborratsOK = 0;
public int FitxersEsborratsKO = 0;
public int CarpetesSenseFitxers = 0;
public int CarpetesPwdIncorrecte = 0;
public int CarpetesJaDesxifrades = 0;
public int CarpetesSenseFitxerConfiguracio = 0;
public string AString()
{
StringBuilder SB = new StringBuilder();
SB.AppendFormat("Fitxers desxifrats OK: {0}{1}", FitxersDesxifratsOK, Environment.NewLine);
SB.AppendFormat("Fitxers desxifrats KO: {0}{1}", FitxersDesxifratsKO, Environment.NewLine);
SB.AppendFormat("Fitxers esborrats OK: {0}{1}", FitxersEsborratsOK, Environment.NewLine);
SB.AppendFormat("Fitxers esborrats KO: {0}{1}", FitxersEsborratsKO, Environment.NewLine);
SB.AppendFormat("Carpetes sense fitxers: {0}{1}", CarpetesSenseFitxers, Environment.NewLine);
SB.AppendFormat("Carpetes pwd incorrecte: {0}{1}", CarpetesPwdIncorrecte, Environment.NewLine);
SB.AppendFormat("Carpetes ja desxifrades: {0}{1}", CarpetesJaDesxifrades, Environment.NewLine);
SB.AppendFormat("Carpetes sense fitxer config: {0}{1}", CarpetesSenseFitxerConfiguracio, Environment.NewLine);
return SB.ToString();
}
}
I una altra:
class clsDadesVerificacioRetorn
{
public int FitxersVerificats = 0;
public int FitxersHashDiferent = 0;
public int FitxersEsborrats = 0;
public int FitxersMidaDiferent = 0;
public string AString()
{
StringBuilder SB = new StringBuilder();
SB.AppendFormat("Total fitxers OK: {0}.{1}", FitxersVerificats, Environment.NewLine);
SB.AppendFormat("Hash KO: {0}.{1}", FitxersHashDiferent, Environment.NewLine);
SB.AppendFormat("Esborrats: {0}.{1}", FitxersEsborrats, Environment.NewLine);
SB.AppendFormat("Mida diferent: {0}.{1}", FitxersMidaDiferent, Environment.NewLine);
return SB.ToString();
}
}
I l'última:
class clsDadesXifratRetorn
{
public int FitxersXifratsOK = 0;
public int FitxersXifratsKO = 0;
public int FitxersEsborratsOK = 0;
public int FitxersEsborratsKO = 0;
public int FitxersReadonly = 0;
public int FitxersTamany0 = 0;
public int FitxersOcults = 0;
public int CarpetesJaXifrades = 0;
public int CarpetesSenseFitxerConfiguracio = 0;
public string AString()
{
StringBuilder SB = new StringBuilder();
SB.AppendFormat("Fitxers xifrats OK: {0}{1}", FitxersXifratsOK, Environment.NewLine);
SB.AppendFormat("Fitxers xifrats KO: {0}{1}", FitxersXifratsKO, Environment.NewLine);
SB.AppendFormat("Fitxers esborrats OK: {0}{1}", FitxersEsborratsOK, Environment.NewLine);
SB.AppendFormat("Fitxers esborrats KO: {0}{1}", FitxersEsborratsKO, Environment.NewLine);
SB.AppendFormat("Fitxers readonly: {0}{1}", FitxersReadonly, Environment.NewLine);
SB.AppendFormat("Fitxers tamany 0: {0}{1}", FitxersTamany0, Environment.NewLine);
SB.AppendFormat("Fitxers ocults: {0}{1}", FitxersOcults, Environment.NewLine);
SB.AppendFormat("Carpetes ja xifrades: {0}{1}", CarpetesJaXifrades, Environment.NewLine);
SB.AppendFormat("Carpetes sense fitxer config: {0}{1}", CarpetesSenseFitxerConfiguracio, Environment.NewLine);
return SB.ToString();
}
}
| #07/01/2020 16:59 Programació C# Autor: Alex Canalda
|
El petit hashejador ha crescut |
El petit hashejador ha rebut queixes del seu usuari principal, jo, i clar el desenvolupador ha tingut que fer-li cas, jo mateix. Així que l'he afegit algunes funcionalitats més.
- "crea path [-r] [-desde_cero]:" crea un fitxer XML amb els Hash dels fitxers. -r indica recursiu. -desde_cero: esborra els fitxers de hashos existents. Si no es posa aquesta opció si ja existeix el fitxeret de hashos es salta la carpeta.
- "verifica path [-r] [-continua]" verifica que els fitxers tinguin el Hash correcte, -r indica recursiu, -continua no verifica els fitxers en estat VERIFICAT. Clar hem vaig trobar que el procés de verificació de moooolts fitxers triga, i volia un procés que pugui ser interromput i que continuï des d'on ho va deixar en un altra moment. La verificació guarda el fitxer de hashos cada 5GB de fitxers processat i quan acaba de verificar la carpeta.
- "resultats path [-r]" no calcula hashos, llegeix els fitxers del hasher buscant fitxers amb modificacions, errors i esborrats. -r indica recursiu. Si deixes la finestra amb el verifica fent, clar, potser et perds els errors o algo. Aleshores el resultats els ensenya.
- "actualitza path [-r]" calcula hashos per fitxers nous, esborra del fitxer de hashos els que pertanyen a fitxers esborrats, -r indica recursiu.
- "reset path [-r]" reseteja l'estat a PENDENT, -r indica recursiu. Clar, el verifica posa l'estat del fitxer a "VERIFICAT", cal doncs alguna forma de tornar a començar sense crear el fitxer de cero. Així es poden llançar verificacions en diferents dies. Primer un "reset" i després un "verifica".
Com sempre el codi, primer l'aplicació de consola, després la clase:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace Hasher
{
class Program
{
private static string ExecutablePath = "";
private static string CarpetaAProcessar = "";
private static bool Recursiu = false;
private static bool Creacio_de_cero = false;
private static string Accio = "";
private static bool Continua = false;
static void Main(string[] args)
{
string AppPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
ExecutablePath = Path.GetDirectoryName(AppPath);
try
{
if (args.Length > 0)
{
ParseParams(args);
if (CarpetaAProcessar != "")
{
if (!Directory.Exists(CarpetaAProcessar))
{
Console.WriteLine("Carpeta no trobada: " + CarpetaAProcessar);
return;
}
}
else
{
Console.WriteLine("Carpeta a processar no informada");
return;
}
switch (Accio)
{
case "crea":
crea(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - creació acabada.");
break;
case "verifica":
verifica(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - verificació acabada.");
break;
case "resultats":
resultats(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - obtenir resultats acabat.");
break;
case "actualitza":
actualitza(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - actualitza acabat.");
break;
case "reset":
reset(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - reset acabat.");
break;
default:
Console.WriteLine("Possibles parametres:");
Console.WriteLine("\"crea path [-r] [-desde_cero]\" crea un fitxer XML amb els Hash dels fitxers. "
+ "-r indica recursiu. -desde_cero: esborra els fitxers de hashos existents.");
Console.WriteLine("\"verifica path [-r] [-continua]\" verifica que els fitxers tinguin el Hash correcte, "
+ "-r indica recursiu, -continua no verifica els fitxers en estat VERIFICAT");
Console.WriteLine("\"resultats path [-r]\" no calcula hashos, llegeix els fitxers del hasher buscant "
+ " fitxers amb modificacions, -r indica recursiu");
Console.WriteLine("\"actualitza path [-r]\" calcula hashos per fitxers nous, "
+ "esborra del fitxer de hashos els que pertanyen a fitxers esborrats, -r indica recursiu");
Console.WriteLine("\"reset path [-r]\" reseteja l'estat a PENDENT, -r indica recursiu");
break;
}
}
else
{
Console.WriteLine("Possibles parametres:");
Console.WriteLine("Possibles parametres:");
Console.WriteLine("\"crea path [-r] [-desde_cero]\" crea un fitxer XML amb els Hash dels fitxers. "
+ "-r indica recursiu. -desde_cero: esborra els fitxers de hashos existents.");
Console.WriteLine("\"verifica path [-r] [-continua]\" verifica que els fitxers tinguin el Hash correcte, "
+ "-r indica recursiu, -continua no verifica els fitxers en estat VERIFICAT");
Console.WriteLine("\"resultats path [-r]\" no calcula hashos, llegeix els fitxers del hasher buscant "
+ " fitxers amb modificacions, -r indica recursiu");
Console.WriteLine("\"actualitza path [-r]\" calcula hashos per fitxers nous, "
+ "esborra del fitxer de hashos els que pertanyen a fitxers esborrats, -r indica recursiu");
Console.WriteLine("\"reset path [-r]\" reseteja l'estat a PENDENT, -r indica recursiu");
}
}
catch(Exception Err)
{
Console.WriteLine(Err.Source + " - " + Err.TargetSite + "-" + Err.Message);
}
}
private static void reset(string pPath)
{
if (!File.Exists(pPath + "\\hasher.xml"))
{
Console.WriteLine(ObtenirData() + " - No hi ha fitxer de hashos: " + pPath);
}
else
{
Dictionary<string, clsFitxer> DicFitxers;
DicFitxers = CarregaHashos(pPath);
Console.WriteLine(ObtenirData() + " - resetejant: " + pPath);
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
objFitxer.Value.Estat = "PENDENT";
}
Save(pPath, DicFitxers);
}
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
reset(Carpeta);
}
}
}
public static string SHA256HashFile(string sPath)
{
string sHash = "";
using (var stream = new BufferedStream(File.OpenRead(sPath), 2400000))
{
SHA256CryptoServiceProvider sha256h = new SHA256CryptoServiceProvider();
sHash = BitConverter.ToString(sha256h.ComputeHash(stream));
}
return sHash;
}
private static void actualitza(string pPath)
{
if (!File.Exists(pPath + "\\hasher.xml"))
{
Console.WriteLine(ObtenirData() + " - No hi ha fitxer de hashos: " + pPath);
}
else
{
Dictionary<string, clsFitxer> DicFitxers;
Dictionary<string, clsFitxer> FitxersActualitzats = new Dictionary<string, clsFitxer>();
clsFitxer FitxerActualitzat = null;
DicFitxers = CarregaHashos(pPath);
DirectoryInfo dir = new DirectoryInfo(pPath);
FileInfo[] Fitxers = dir.GetFiles();
Console.WriteLine(ObtenirData() + " - Processant " + pPath);
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
try
{
if (File.Exists(pPath + "\\ " + objFitxer.Value.Nom))
{
FitxerActualitzat = new clsFitxer(objFitxer.Value.Nom,
objFitxer.Value.DataCreacio,
objFitxer.Value.DataVerificacio,
objFitxer.Value.MidaEnBytes,
objFitxer.Value.Hash,
objFitxer.Value.Estat);
FitxersActualitzats.Add(FitxerActualitzat.Nom, FitxerActualitzat);
}
}
catch (IOException e)
{
Console.WriteLine("I/O Exception: " + e.Message);
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("Access Exception: " + e.Message);
}
}
foreach (FileInfo Fitxer in Fitxers)
{
if (!DicFitxers.ContainsKey(Fitxer.Name))
{
if (Fitxer.Name.ToLower() != "hasher.exe" && Fitxer.Name.ToLower() != "hasher.xml")
{
string hashValueStr = SHA256HashFile(Fitxer.FullName);
Console.WriteLine(ObtenirData() + " - hashejat: " + Fitxer.Name);
FitxerActualitzat = new clsFitxer(Fitxer.Name, DateTime.Now,
DateTime.Now,
Fitxer.Length,
hashValueStr,
"CREAT");
FitxersActualitzats.Add(Fitxer.Name, FitxerActualitzat);
}
}
}
Save(pPath, FitxersActualitzats);
}
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
actualitza(Carpeta);
}
}
}
private static void ParseParams(string[] args)
{
for(int i = 0; i<args.Length; i++)
{
if(args[i].ToLower() == "crea")
{
Accio = "crea";
}
if (args[i].ToLower() == "verifica")
{
Accio = "verifica";
}
if (args[i].ToLower() == "resultats")
{
Accio = "resultats";
}
if (args[i].ToLower() == "actualitza")
{
Accio = "actualitza";
}
if (args[i].ToLower() == "reset")
{
Accio = "reset";
}
if (args[i].ToLower() == "-r")
{
Recursiu = true;
}
if (args[i].ToLower() == "-desde_cero")
{
Creacio_de_cero = true;
}
if (args[i].ToLower() == "-continua")
{
Continua = true;
}
if(args[i].Contains(":"))
{
CarpetaAProcessar = args[i].Replace("\\\\ ", "\\ ");
}
}
}
private static void resultats(string pPath)
{
if (!File.Exists(pPath + "\\hasher.xml"))
{
Console.WriteLine(ObtenirData() + " - No hi ha fitxer de hashos: " + pPath);
}
else
{
Dictionary<string, clsFitxer> DicFitxers;
DicFitxers = CarregaHashos(pPath);
Console.WriteLine(ObtenirData() + " - analitzant: " + pPath);
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
if(objFitxer.Value.Estat == "NO COINCIDEIX")
{
Console.WriteLine(ObtenirData(objFitxer.Value.DataVerificacio)
+ " - fitxer amb hash canviat: " + pPath + "\\ " + objFitxer.Value.Nom);
}
else
{
if(objFitxer.Value.Estat.Contains("MIDA DIFERENT"))
{
Console.WriteLine(ObtenirData(objFitxer.Value.DataVerificacio)
+ " - fitxer amb mida diferent: " + pPath + "\\ " + objFitxer.Value.Nom);
}
else
{
if (objFitxer.Value.Estat == "ESBORRAT")
{
Console.WriteLine(ObtenirData(objFitxer.Value.DataVerificacio)
+ " - fitxer esborrat: " + pPath + "\\ " + objFitxer.Value.Nom);
}
}
}
}
}
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
resultats(Carpeta);
}
}
}
public static string ObtenirData(DateTime data)
{
return data.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture);
}
public static string ObtenirData()
{
return DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture);
}
public static void verifica(string pPath)
{
long GBHashejats = 0;
Console.WriteLine(ObtenirData() + " - verificant carpeta: " + pPath);
if (!File.Exists(pPath + "\\hasher.xml"))
{
Console.WriteLine(ObtenirData() + " - No hi ha fitxer de hashos: " + pPath);
}
else
{
Dictionary<string, clsFitxer> DicFitxers;
DicFitxers = CarregaHashos(pPath);
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
if (objFitxer.Value.Estat == "VERIFICAT" && Continua)
{
Console.WriteLine(ObtenirData() + " - fitxer ja verificat anteriorment: " + objFitxer.Value.Nom);
}
else
{
try
{
if (File.Exists(pPath + "\\ " + objFitxer.Value.Nom))
{
FileInfo fiFitxer = new FileInfo(pPath + "\\ " + objFitxer.Value.Nom);
if (fiFitxer.Length != objFitxer.Value.MidaEnBytes)
{
Console.WriteLine(ObtenirData() + " - Fitxer amb mida diferent: " + fiFitxer.Name);
objFitxer.Value.Estat = "MIDA DIFERENT, actual: " + fiFitxer.Length;
}
else
{
GBHashejats += fiFitxer.Length;
string hashValueStr = SHA256HashFile(fiFitxer.FullName);
if (hashValueStr == objFitxer.Value.Hash)
{
objFitxer.Value.Estat = "VERIFICAT";
}
else
{
Console.WriteLine(ObtenirData() + " - Fitxer amb hash canviat: " + fiFitxer.Name);
objFitxer.Value.Estat = "NO COINCIDEIX";
}
if(GBHashejats > 5368709120)
{
GBHashejats = 0;
Save(pPath, DicFitxers);
}
}
}
else
{
Console.WriteLine(ObtenirData() + " - Fitxer esborrat: " + objFitxer.Value.Nom);
objFitxer.Value.Estat = "ESBORRAT";
}
objFitxer.Value.DataVerificacio = DateTime.Now;
}
catch (IOException e)
{
Console.WriteLine("I/O Exception: " + e.Message);
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("Access Exception: " + e.Message);
}
}
}
Save(pPath, DicFitxers);
}
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
foreach(string Carpeta in Carpetes)
{
verifica(Carpeta);
}
}
}
public static Dictionary<string, clsFitxer> CarregaHashos(string pPath)
{
XmlDocument Doc = new XmlDocument();
XmlNode Fitxers;
XmlNodeList llistaDeFitxer;
XmlNode Nom;
XmlNode Hash;
XmlNode DataCreacio;
XmlNode DataVerificacio;
XmlNode Estat;
XmlNode MidaEnBytes;
clsFitxer objFitxer = null;
Dictionary<string, clsFitxer> DicFitxers = new Dictionary<string, clsFitxer>();
Doc.Load(pPath + "\\hasher.xml");
Fitxers = Doc.SelectSingleNode("descendant::fitxers");
llistaDeFitxer = Fitxers.ChildNodes;
foreach (XmlNode Fitxer in llistaDeFitxer)
{
objFitxer = new clsFitxer();
Nom = Fitxer.SelectSingleNode("descendant::nom");
Hash = Fitxer.SelectSingleNode("descendant::hash");
DataCreacio = Fitxer.SelectSingleNode("descendant::datacreacio");
DataVerificacio = Fitxer.SelectSingleNode("descendant::dataverificacio");
Estat = Fitxer.SelectSingleNode("descendant::estat");
MidaEnBytes = Fitxer.SelectSingleNode("descendant::midaenbytes");
objFitxer.Nom = Nom.InnerText;
objFitxer.Hash = Hash.InnerText;
objFitxer.DataCreacio = DateTime.ParseExact(DataCreacio.InnerText, "dd/MM/yyyy HH:mm:ss", null);
objFitxer.DataVerificacio = DateTime.ParseExact(DataVerificacio.InnerText, "dd/MM/yyyy HH:mm:ss", null);
objFitxer.Estat = Estat.InnerText;
objFitxer.MidaEnBytes = long.Parse(MidaEnBytes.InnerText);
DicFitxers.Add(objFitxer.Nom, objFitxer);
}
return DicFitxers;
}
public static void crea(string pPath)
{
bool Procesa_carpeta = false;
if (File.Exists(pPath + "\\hasher.xml"))
{
if (Creacio_de_cero)
{
File.Delete(pPath + "\\hasher.xml");
Console.WriteLine(ObtenirData() + " - Carpeta " + pPath + " amb fitxer de hashos, esborrat.");
Procesa_carpeta = true;
}
else
{
Console.WriteLine(ObtenirData() + " - Carpeta " + pPath + " amb fitxer de hashos, no procesada.");
Procesa_carpeta = false;
}
}
if (Procesa_carpeta)
{
Console.WriteLine(ObtenirData() + " - creant fitxer hashos: " + pPath);
DirectoryInfo dir = new DirectoryInfo(pPath);
FileInfo[] files = dir.GetFiles();
clsFitxer objFitxer = null;
Dictionary<string, clsFitxer> DicFitxers = new Dictionary<string, clsFitxer>();
foreach (FileInfo Fitxer in files)
{
try
{
if (Fitxer.Name.ToLower() != "hasher.exe" && Fitxer.Name.ToLower() != "hasher.xml")
{
string hashValueStr = SHA256HashFile(Fitxer.FullName);
Console.WriteLine(ObtenirData() + " - hashejat: " + Fitxer.Name);
objFitxer = new clsFitxer(Fitxer.Name,
DateTime.Now,
DateTime.Now,
Fitxer.Length,
hashValueStr,
"CREAT");
DicFitxers.Add(Fitxer.Name, objFitxer);
}
}
catch (IOException e)
{
Console.WriteLine("I/O Exception: " + e.Message);
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("Access Exception: " + e.Message);
}
}
Save(pPath, DicFitxers);
}
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
crea(Carpeta);
}
}
}
public static void Save(string pPath, Dictionary<string, clsFitxer> DicFitxers)
{
XmlDocument Doc = new XmlDocument();
XmlNode Fitxers;
XmlNode Fitxer;
XmlNode Nom;
XmlNode Hash;
XmlNode DataCreacio;
XmlNode DataVerificacio;
XmlNode Estat;
XmlNode MidaEnBytes;
Doc.LoadXml("<?xml version=\ "1.0\ " standalone=\ "yes\ "?><fitxers></fitxers>");
Fitxers = Doc.SelectSingleNode("descendant::fitxers");
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
Fitxer = Doc.CreateNode(XmlNodeType.Element, "fitxer", "");
Nom = Doc.CreateNode(XmlNodeType.Element, "nom", "");
Hash = Doc.CreateNode(XmlNodeType.Element, "hash", "");
DataCreacio = Doc.CreateNode(XmlNodeType.Element, "datacreacio", "");
DataVerificacio = Doc.CreateNode(XmlNodeType.Element, "dataverificacio", "");
Estat = Doc.CreateNode(XmlNodeType.Element, "estat", "");
MidaEnBytes = Doc.CreateNode(XmlNodeType.Element, "midaenbytes", "");
Nom.InnerText = objFitxer.Value.Nom;
Hash.InnerText = objFitxer.Value.Hash;
DataCreacio.InnerText = ObtenirData(objFitxer.Value.DataCreacio);
DataVerificacio.InnerText = ObtenirData(objFitxer.Value.DataVerificacio);
Estat.InnerText = objFitxer.Value.Estat;
MidaEnBytes.InnerText = objFitxer.Value.MidaEnBytes.ToString();
Fitxer.AppendChild(Nom);
Fitxer.AppendChild(Hash);
Fitxer.AppendChild(DataCreacio);
Fitxer.AppendChild(DataVerificacio);
Fitxer.AppendChild(Estat);
Fitxer.AppendChild(MidaEnBytes);
Fitxers.AppendChild(Fitxer);
}
Doc.Save(pPath + "\\hasher.xml");
}
}
}
Ara la clase:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hasher
{
class clsFitxer
{
public string Nom { get; set; }
public DateTime DataCreacio { get; set; }
public DateTime DataVerificacio { get; set; }
public long MidaEnBytes { get; set; }
public string Hash { get; set; }
public string Estat { get; set; }
public clsFitxer()
{
}
public clsFitxer(string pNom,
DateTime pDataCreacio,
DateTime pDataVerificacio,
long pMidaEnBytes,
string pHash,
string pEstat)
{
Nom = pNom;
DataCreacio = pDataCreacio;
DataVerificacio = pDataVerificacio;
MidaEnBytes = pMidaEnBytes;
Hash = pHash;
Estat = pEstat;
}
}
}
| #29/07/2019 09:28 Programació C# Autor: Alex Canalda
|
2WSSL (a.k.a Mutual authentication) en C# |
Quan s'estableix una comunicació amb un servidor es pot fer xifrada. Actualment gairebé totes les connexions són xifrades, es coneix com SSL. En una connexió SSL normalment s'identifica el servidor, el client que es connecta no. Però els servidors poden anar un pas més enllà i demanar al client que s'identifiqui. Això es coneix amb varis noms, 2-way SSL, 2WSSL o Mutual authentication.
Quan es programa s'ha de tenir en compte que calen uns passos extra per configurar la connexió. Cal afegir un certificat que identifiqui al client i que alguna CA (certificate authority) del servidor validi (reconegui). El curiós és que el certificat acostuma a estar guardat en un fitxer P12, però un contenidor P12 pot tenir més d'un al seu interior. No he trobat en la llibreria C# d'accés al P12 cap forma d'accedir posant el nom del certificat. Així que millor posar un P12 que contingui un únic certificat. Les variables CertStorageP12, PwdCertStorage són la ruta d'accés al fitxer (el path amb el nom del fitxer) i la contrasenya.
HttpWebRequest req = WebRequest.CreateHttp(URL);
X509Certificate2 cert = null;
X509CertificateCollection certColl = null;
cert = new X509Certificate2(CertStorageP12, PwdCertStorage, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
certColl = new X509CertificateCollection();
certColl.Add(cert);
req.ClientCertificates = certColl;
req.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequired;
| #19/07/2019 14:26 Programació C# Autor: Alex Canalda
|
El petit hashejador |
Fa un temps vaig fer el hashejador, un software multifil que per cada disc dur calcula el hash dels fitxers que estan en un BBDD i compara el resultat amb el que ja té guardat. Serveix per protegir-se del bit rotting. El cert és que hem va força bé, quan tingui temps el milloraré per fer servir SHA256 enlloc de SHA1 però això serà una altra història. L'inconvenient que li veig al hashejador és que necessita una BBDD, una infraestructura, etc...
El PowerShell disposa d'una comanda Get-FileHash que calcula hashs de fitxers, però no els guarda enlloc, els treu per pantalla. Suposo que es podria escriure alguna utilitat que el guardi en un fitxer de text però aleshores també caldria escriure una altra "cosa" (referint-me al llenguatge del PowerShell) per tal que compari els hashs existents amb el que es calcula en aquell moment. Però jo no sóc de fer coses en PowerShell.
Per això ha sortit el petit hashejador, una utilitat per calcular els hash de fitxers i deixar el resultat en un fitxer XML dins la mateixa carpeta on estan els fitxers. Més endavant el petit hashejador pot fer el procés de verificació per veure que tot està a lloc. El problema que li veig és que permet detectar errors però no corregir-los, es a dir el petit hashejador et dirà que no li encaixa la verificació d'un fitxer però un cop detectat... que fas? Com el recuperes? Això ho fa el seu germà gran que verifica un fitxer en diferents discs durs i llavors saps quina còpia és la bona. Però de moment, el petit hashejador només fa això, detectar sense corregir.
El petit hashejador és una aplicació de línia de comandes (o "aplicación de consola") formada per un programa principal i una classe. El programa principal té la funció de verificar i la de crear el fitxeret amb els hashos, la de guardar i llegir el fitxer XML. No és que sigui gaire complicat. Primer el programa principal:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace Hasher
{
class Program
{
private static string ExecutablePath = "";
private static string CarpetaAProcessar = "";
private static bool Recursiu = false;
static void Main(string[] args)
{
string AppPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
ExecutablePath = Path.GetDirectoryName(AppPath);
try
{
if (args.Length > 0)
{
string Accio = args[0].ToLower();
if (args.Length > 1)
{
if (args[1] != null)
{
CarpetaAProcessar = args[1];
}
}
if (args.Length > 2)
{
if (args[2] != null)
{
if (args[2].ToLower() == "-r")
{
Recursiu = true;
}
}
}
if (CarpetaAProcessar != "")
{
if (!Directory.Exists(CarpetaAProcessar))
{
Console.WriteLine("Carpeta no trobada: " + CarpetaAProcessar);
return;
}
}
else
{
Console.WriteLine("Carpeta a processar no informada");
return;
}
switch (Accio)
{
case "crea":
crea(CarpetaAProcessar);
break;
case "verifica":
if (!File.Exists(CarpetaAProcessar + "\\hasher.xml"))
{
Console.WriteLine("No hi ha fitxer de hashos.");
return;
}
verifica(CarpetaAProcessar);
break;
default:
Console.WriteLine("Possibles parametres:");
Console.WriteLine("\"crea path [-r]\" crea un fitxer XML amb els Hash dels fitxers, -r indica recursiu");
Console.WriteLine("\"verifica path [-r]\" verifica que els fitxers tinguin el Hash -r indica recursiu");
break;
}
}
else
{
Console.WriteLine("Possibles parametres:");
Console.WriteLine("\"crea path [-r]\" crea un fitxer XML amb els Hash dels fitxers -r indica recursiu");
Console.WriteLine("\"verifica path [-r]\" verifica que els fitxers tinguin el Hash -r indica recursiu");
}
}
catch(Exception Err)
{
Console.WriteLine(Err.Message);
}
}
public static string ObtenirData(DateTime data)
{
return data.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture);
}
public static string ObtenirData()
{
return DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture);
}
public static void verifica(string pPath)
{
Console.WriteLine(ObtenirData() + " - verificant carpeta: " + pPath);
SHA256 mySHA256 = SHA256.Create();
Dictionary<string, clsFitxer> DicFitxers;
DicFitxers = CarregaHashos(pPath);
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
try
{
if (File.Exists(pPath + "\\ " + objFitxer.Value.Nom))
{
FileInfo fiFitxer = new FileInfo(pPath + "\\ " + objFitxer.Value.Nom);
if (fiFitxer.Length != objFitxer.Value.MidaEnBytes)
{
Console.WriteLine("Fitxer amb mida diferent: " + fiFitxer.Name);
objFitxer.Value.Estat = "MIDA DIFERENT, actual: " + fiFitxer.Length;
}
else
{
FileStream fileStream = fiFitxer.Open(FileMode.Open, FileAccess.Read, FileShare.None);
fileStream.Position = 0;
byte[] hashValue = mySHA256.ComputeHash(fileStream);
string hashValueStr = ConvertByteArrayToHexString(hashValue);
fileStream.Close();
if (hashValueStr == objFitxer.Value.Hash)
{
objFitxer.Value.Estat = "VERIFICAT";
}
else
{
Console.WriteLine("Fitxer amb hash canviat: " + fiFitxer.Name);
objFitxer.Value.Estat = "NO COINCIDEIX";
}
}
}
else
{
objFitxer.Value.Estat = "ESBORRAT";
}
objFitxer.Value.DataVerificacio = DateTime.Now;
}
catch (IOException e)
{
Console.WriteLine($"I/O Exception: {e.Message}");
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine($"Access Exception: {e.Message}");
}
}
Save(pPath, DicFitxers);
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
foreach(string Carpeta in Carpetes)
{
verifica(Carpeta);
}
}
}
public static Dictionary<string, clsFitxer> CarregaHashos(string pPath)
{
XmlDocument Doc = new XmlDocument();
XmlNode Fitxers;
XmlNodeList llistaDeFitxer;
XmlNode Nom;
XmlNode Hash;
XmlNode DataCreacio;
XmlNode DataVerificacio;
XmlNode Estat;
XmlNode MidaEnBytes;
clsFitxer objFitxer = null;
Dictionary<string, clsFitxer> DicFitxers = new Dictionary<string, clsFitxer>();
Doc.Load(pPath + "\\hasher.xml");
Fitxers = Doc.SelectSingleNode("descendant::fitxers");
llistaDeFitxer = Fitxers.ChildNodes;
foreach (XmlNode Fitxer in llistaDeFitxer)
{
objFitxer = new clsFitxer();
Nom = Fitxer.SelectSingleNode("descendant::nom");
Hash = Fitxer.SelectSingleNode("descendant::hash");
DataCreacio = Fitxer.SelectSingleNode("descendant::datacreacio");
DataVerificacio = Fitxer.SelectSingleNode("descendant::dataverificacio");
Estat = Fitxer.SelectSingleNode("descendant::estat");
MidaEnBytes = Fitxer.SelectSingleNode("descendant::midaenbytes");
objFitxer.Nom = Nom.InnerText;
objFitxer.Hash = Hash.InnerText;
objFitxer.DataCreacio = DateTime.ParseExact(DataCreacio.InnerText, "dd/MM/yyyy HH:mm:ss", null);
objFitxer.DataVerificacio = DateTime.ParseExact(DataVerificacio.InnerText, "dd/MM/yyyy HH:mm:ss", null);
objFitxer.Estat = Estat.InnerText;
objFitxer.MidaEnBytes = long.Parse(MidaEnBytes.InnerText);
DicFitxers.Add(objFitxer.Nom, objFitxer);
}
return DicFitxers;
}
public static void crea(string pPath)
{
Console.WriteLine(ObtenirData() + " - creant fitxer hashos: " + pPath);
if (File.Exists(pPath + "\\hasher.xml"))
{
File.Delete(pPath + "\\hasher.xml");
}
SHA256 mySHA256 = SHA256.Create();
DirectoryInfo dir = new DirectoryInfo(pPath);
FileInfo[] files = dir.GetFiles();
clsFitxer objFitxer = null;
Dictionary<string, clsFitxer> DicFitxers = new Dictionary<string, clsFitxer>();
foreach (FileInfo Fitxer in files)
{
try
{
if (Fitxer.Name.ToLower() != "hasher.exe" && Fitxer.Name.ToLower() != "hasher.xml")
{
FileStream fileStream = Fitxer.Open(FileMode.Open);
fileStream.Position = 0;
byte[] hashValue = mySHA256.ComputeHash(fileStream);
string hashValueStr = ConvertByteArrayToHexString(hashValue);
fileStream.Close();
objFitxer = new clsFitxer(Fitxer.Name, DateTime.Now, DateTime.Now, Fitxer.Length, hashValueStr, "CREAT");
DicFitxers.Add(Fitxer.Name, objFitxer);
}
}
catch (IOException e)
{
Console.WriteLine($"I/O Exception: {e.Message}");
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine($"Access Exception: {e.Message}");
}
}
Save(pPath, DicFitxers);
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
crea(Carpeta);
}
}
}
public static void Save(string pPath, Dictionary<string, clsFitxer> DicFitxers)
{
XmlDocument Doc = new XmlDocument();
XmlNode Fitxers;
XmlNode Fitxer;
XmlNode Nom;
XmlNode Hash;
XmlNode DataCreacio;
XmlNode DataVerificacio;
XmlNode Estat;
XmlNode MidaEnBytes;
Doc.LoadXml("<?xml version=\"1.0\" standalone=\"yes\"?><fitxers></fitxers>");
Fitxers = Doc.SelectSingleNode("descendant::fitxers");
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
Fitxer = Doc.CreateNode(XmlNodeType.Element, "fitxer", "");
Nom = Doc.CreateNode(XmlNodeType.Element, "nom", "");
Hash = Doc.CreateNode(XmlNodeType.Element, "hash", "");
DataCreacio = Doc.CreateNode(XmlNodeType.Element, "datacreacio", "");
DataVerificacio = Doc.CreateNode(XmlNodeType.Element, "dataverificacio", "");
Estat = Doc.CreateNode(XmlNodeType.Element, "estat", "");
MidaEnBytes = Doc.CreateNode(XmlNodeType.Element, "midaenbytes", "");
Nom.InnerText = objFitxer.Value.Nom;
Hash.InnerText = objFitxer.Value.Hash;
DataCreacio.InnerText = ObtenirData(objFitxer.Value.DataCreacio);
DataVerificacio.InnerText = ObtenirData(objFitxer.Value.DataVerificacio);
Estat.InnerText = objFitxer.Value.Estat;
MidaEnBytes.InnerText = objFitxer.Value.MidaEnBytes.ToString();
Fitxer.AppendChild(Nom);
Fitxer.AppendChild(Hash);
Fitxer.AppendChild(DataCreacio);
Fitxer.AppendChild(DataVerificacio);
Fitxer.AppendChild(Estat);
Fitxer.AppendChild(MidaEnBytes);
Fitxers.AppendChild(Fitxer);
}
Doc.Save(pPath + "\\hasher.xml");
}
public static string ConvertByteArrayToHexString(byte[] ba)
{
StringBuilder sb = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
{
sb.AppendFormat("{0:x2}", b);
}
return sb.ToString().ToUpper();
}
}
}
Després la classe:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hasher
{
class clsFitxer
{
public string Nom { get; set; }
public DateTime DataCreacio { get; set; }
public DateTime DataVerificacio { get; set; }
public long MidaEnBytes { get; set; }
public string Hash { get; set; }
public string Estat { get; set; }
public clsFitxer()
{
}
public clsFitxer(string pNom, DateTime pDataCreacio, DateTime pDataVerificacio, long pMidaEnBytes, string pHash, string pEstat)
{
Nom = pNom;
DataCreacio = pDataCreacio;
DataVerificacio = pDataVerificacio;
MidaEnBytes = pMidaEnBytes;
Hash = pHash;
Estat = pEstat;
}
}
}
I fet! | #29/04/2019 17:36 Programació C# Autor: Alex Canalda
|
Separació de poders... |
A vegades veig llenguatges de programació que penso... "quina llumenera haurà fet això?".
Són llenguatges on va tot empotrat, com el Razor. Són llenguatges on es barreja tot, l'HTML amb lògica, amb dades... Entenc que en el món ha d'haver-hi de tot i al gust de tothom. Així que la mateixa empresa (en aquest cas MS) desenvolupa molts llenguatges per cobrir els gustos de tots. Articles com aquest em fan sagnar els ulls...
Aquí va tot barrejat..., els events? Cap dins. L'estil? Cap dins. Les dades? Cap dins...
Penso que en un equip de programadors hi ha gent que en sap més, gent que menys, i ara que hem toca repartir tasques entre persones ja se de quin peu calça cadascú. Aleshores quan tinc que passar-lis feina, al que sap HTML li passo HTML, el que li va el Javascript li passo Javascript, el de codi servidor, el de SQLs... Així ells (els programadors) estan contents, triguen menys i el resultat és de millor qualitat. Tampoc obligo a saber de tot i es poden especialitzar. Si saps de tot al final no saps el detall que fa que no funcioni el que fas, i perds temps buscant-lo.
Així doncs penso que millor cada element separat, HTML, CSS, dades, enviament/recepció de dades del servidor. De fet tal com treballo puc canviar un servidor web per un altra d'una tecnologia diferent si compleixo una "API" o un cert format JSON acordat entre la part que està al navegador i la part servidora, sense tocar ni un punt d'aquesta. Llavors no entenc per que ho volen tot barrejat. Potser per prototipus o temes molt ràpids... si no, no veig la raó de l'existència dels llenguatges barrejats. Jo prefereixo els poders separats... | #02/08/2018 14:15 Programació C# Javascript Autor: Alex Canalda
|
<< Posts anteriors |
|