He vist aquesta sèrie curta sobre superherois i anti-herois. Hi ha de tot, capítols més brillants, capítols més avorrits, però en general està força bé. Ara estic esperant la segona temporada. Curiós que surt a Amazon Prime, però la descarrego igualment ¿? Suposo que per costum, inèrcia, ...
[Spoilers] Un superheroi que corre molt s'equivoca i atropella (i mata) una noia que està al carrer amb el seu xicot. Un ex-agent del FBI el recluta per matar superherois i venjar-se. Resulta que a la dóna del l'agent també la va matar un superheroi mentre li posava les banyes. Però resulta que no, que tot era mentida i està viva.
Tot era un muntatge d'una empresa que ven un producte que dóna superpoders a nadons, i que ara també tenen països de l'eix del mal (a.k.a arabs). La jefa de l'empresa dolenta acaba palmant i ara a veure la segona temporada com ho arreglen.[/Spoilers]
M'ha agradat, no és la típica sèrie de superherois. Ara a esperar la T2.
Següent llibre de la sèrie del Temeraire. El cert és que llegeixo menys a l'hivern. Entre el fred, la pluja, que es fa fosc... El ritme baixa. Però el lector infatigable no para, el que aquest llibre tampoc ajuda, està bé, però és tranquil. No té una emoció continguda que dius: "uis! que passarà? corre, corre, llegim més...", no, no té d'això. Els personatges van fent i de tant en tant una mica d'acció, s'acaba i fins la següent. I a més li passa com al Sharpe i com a les sèries de llibres, ja saps que hi ha "sopocientos" llibres més així que els personatges principals adquireixen una certa aurea d'invencibilitat o inmunitat, saps que no poden morir ja que en cas contrari s'acabaria el tema... Així que aquesta acció que hi ha repartida és "light".
[Spoilers] Resulta que el Temerarie és un drac de la raça "celestial" i aquests només estan permesos a "Emperadors", els xinesos per això el van donar a Napoleó, però clar en Laurence és un capità de vaixell. Així que l'emperador de Xina envia al seu germà a recuperar-lo. El primer que intenten és separar al Laurence del Temeraire, però no poden així que decideixen enviar-lo a Xina. Mig llibre o més és el viatge... Total que arriben després d'algunes peripècies, intents d'assassinat, serps marines gegants... Un cop a Xina tenen que aconseguir audiència amb l'Emperador, però la cosa va lenta, així que segueixen els intents d'assassinat, fins que en un d'aquests es carreguen sense voler el germà de l'Emperador. Resulta que aquest germà era el dolent que tota l'estona està enviant assassins per que és un retrograd que no vol contacte amb Occident i menys en tema dracs. A més conspirava contra l'Emperador per usurpar-li el tro. Per això l'Emperador anomena fill adoptiu al Laurence i com pertany a la família reial aleshores ja pot tenir un drac celestial.
També el llibre deixa veure que el Temerarie té un bessó igual que ell i que per això van enviar l'ou de drac que sobrava ben lluny, a Napoleó i que a la Xina els dracs tenen drets, saber llegir i escriure, etc... Mentre que a Anglaterra són poc menys que bèsties de càrrega voladores. Per aquest motiu decideixen tornar, per millorar les condicions de vida dels dracs anglesos que estan oprimits. I fi. [/Spoilers]
Doncs ja està tot dit, es deixa llegir, amb tranquil·litat i anar fent. Recomanat? Pse. A veure el següent si millora.
A SQL Server es pot fer un UPDATE d'un camp de tipus text, char, nchar, nvarchar, nchar etc... amb la funció REPLACE. Té els típics 3 paràmetres: On buscar, que buscar i el nou text a posar. Però... sembla que REPLACE no funciona amb camps text, ntext (WTF! Si són texts!). Almenys en el SQL Server 2016. He mirat i no sembla que ho hagin millorat en versions superiors. Molt "Bussiness inteligence" però rascar coses bàsiques costa. En finssss. Però hi ha un forma de fer aquests UPDATES, fent servir el CAST, es a dir convertint el tipus de dada a un que sí li agradi al REPLACE.
UPDATE [tblPaginas]
SET [Contenido] = CAST(REPLACE(CAST([Contenido] asNVarchar(MAX)),'TEXT QUE BUSQUES I VOLS MODIFICAR','NOU TEXT') ASNText)
WHERE [Contenido] LIKE'%ALGUNA CONDICIO%'
Es a dir cal fer un CAST d'anada per posar el text a nvarchar(MAX) i un altra de tornada. I arreglat!
#20/02/2020 13:19 SQLServer Software Autor: Alex Canalda
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();
}
}
}
/// <summary>/// Aquesta funció fa:/// x << 1/// Left-shift of the string x by 1 bit./// The most significant bit disappears, and a zero/// comes into the least significant bit./// 10010001 << 1 is 00100010./// </summary>/// <param name="b">Array de bytes a fer shift</param>/// <returns>El byte shiftejat</returns>byte[] Rol(byte[] b)
{
byte[] r = newbyte[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)
{
/*
// SubKey generation
Figure 2.2 specifies the subkey generation algorithm.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +
+Algorithm Generate_Subkey +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ +
+Input : K(128 - bit key) +
+Output : K1(128 - bit first subkey) +
+K2(128 - bit second subkey) +
+-------------------------------------------------------------------+
+ +
+Constants: const_Zero is 0x00000000000000000000000000000000 +
+const_Rb is 0x00000000000000000000000000000087 +
+Variables: L for output of AES - 128 applied to 0 ^ 128 +
+ +
+Step 1.L := AES - 128(K, const_Zero); +
+Step 2. if MSB(L) is equal to 0 +
+then K1:= L << 1; +
+ else K1:= (L << 1) XOR const_Rb; +
+Step 3. if MSB(K1) is equal to 0 +
+then K2:= K1 << 1; +
+ else K2:= (K1 << 1) XOR const_Rb; +
+Step 4. return K1, K2; +
+ +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Figure 2.2.Algorithm Generate_Subkey
In step 1, AES - 128 with key K is applied to an all-zero input block.
In step 2, K1 is derived through the following operation:
If the most significant bit of L is equal to 0, K1 is the left - shift
of L by 1 bit.
Otherwise, K1 is the exclusive - OR of const_Rb and the left - shift of L
by 1 bit.
In step 3, K2 is derived through the following operation:
If the most significant bit of K1 is equal to 0, K2 is the left - shift
of K1 by 1 bit.
Otherwise, K2 is the exclusive - OR of const_Rb and the left - shift of
K1 by 1 bit.
In step 4, (K1, K2) := Generate_Subkey(K) is returned.
*/// step 1, AES-128 with key K is applied to an all-zero input block.byte[] L = AESEncrypt(key, newbyte[16], newbyte[16]);
// step 2, K1 is derived through the following operation:byte[] FirstSubkey = Rol(L); //If the most significant bit of L is equal to 0, K1 is the left-shift of L by 1 bit.if ((L[0] & 0x80) == 0x80)
FirstSubkey[15] ^= 0x87; // Otherwise, K1 is the exclusive-OR of const_Rb and the left-shift of L by 1 bit.// step 3, K2 is derived through the following operation:byte[] SecondSubkey = Rol(FirstSubkey); // If the most significant bit of K1 is equal to 0, K2 is the left-shift of K1 by 1 bit.if ((FirstSubkey[0] & 0x80) == 0x80)
SecondSubkey[15] ^= 0x87; // Otherwise, K2 is the exclusive-OR of const_Rb and the left-shift of K1 by 1 bit.// MAC computingif (((data.Length != 0) && (data.Length % 16 == 0)) == true)
{
// If the size of the input message block is equal to a positive multiple of the block size (namely, 128 bits),// the last block shall be exclusive-OR'ed with K1 before processingfor (int j = 0; j < FirstSubkey.Length; j++)
data[data.Length - 16 + j] ^= FirstSubkey[j];
}
else
{
//S'afegeix padding a l'ultim bloc, però en realitat és afegir padding a les dades
data = AddPaddingAES(data);
/*
// Otherwise, the last block shall be padded with 10^i
byte[] padding = new byte[16 - data.Length % 16];
padding[0] = 0x80;
data = data.Concat<byte>(padding.AsEnumerable()).ToArray();
*/// and exclusive-OR'ed with K2, la SecondSubkey té 16 de longitudfor (int j = 0; j < 16; j++) data[data.Length - 16 + j] ^= SecondSubkey[j];
}
// The result of the previous process will be the input of the last encryption.byte[] encResult = AESEncrypt(key, newbyte[16], data);
byte[] HashValue = newbyte[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:
//Fent servir BouncyCastle
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 = newbyte[MacLenght];
cMac.BlockUpdate(data, 0, data.Length);
cMac.DoFinal(output, 0);
txtBase64.Text = ConvertByteArrayToHexString(output);
He buscat algo lleuger, per barrejar en mig de scifi i he trobat una barreja rara entre història i fantasia.
Es tracta de "His Majesty's Dragon" d'una autora que es diu "Naomi Novik". L'acció es situa sobre 1804, en l'època de Napoleó amb l'afegit que hi ha dracs... La barreja és curiosa.
[Spoilers] El protagonista és en Laurence, un capità de vaixell. Quan captura un vaixell de guerra francès descobreix que està transportant un ou de drac.
Al principi, com són molt valuosos, estan molt contents però després veuen que està a punt d'obrir-se ja no tant. Es veu que quan un drac neix escull un humà com a amic, i queden vinculats de per vida.
Això fa que el humà passi al Air Royal Corps, que tenen una vida diferent a la resta de la societat típica de l'època. El drac que neix és el Temeraire.
I el drac escull al capità, en Laurence, que no en sap res de cuidar un drac ni quines races hi ha ni res. Al llarg del llibre es va desgranant com encaixa la força aeria draconiana amb l'exèrcit anglés. Com va creixent el drac, quina raça és, que fa...
Al final el drac és un personatge més, una mena d'avió vivent amb tripulació que dispara des d'uns arnesos, que lluita amb altres dracs francesos... Al final hi ha una batalleta amb els francesos curiosa.
El anglesos tenen el canal de la Mànega blocat per la Navy, però els francesos inventen uns transports aeris propulsats per dracs, que van volant, i es disposen a envair Anglaterra.
Gracies al Temerarie que pot emetre una ona sónica destructora s'aconsegueix evitar la invasió. Però es descobreix que el drac és d'una raça xinesa, els Celestials, que només es donen a emperadors i era un regal de l'emperador xinés a Bonaparte. I fi.[/Spoilers]
El llibre es llegeix molt bé i m'ha agradat força, no és gaire llarg, barreja bé l'ambient de l'època amb els dracs. Una sola línia d'acció, sense barrejar personatges, molt bé, molt bé. Recomanat!
... aquest Nadal, i les estacions d'esquí de la muntanya estaven tancades per que feia massa bon temps. Temperatures primaverals.
If you still say that we are wasting valuable lesson time, then let me remind you that our political leaders have wasted decades through denial and inaction
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
{
privatestaticstring ExecutablePath = "";
privatestaticstring Accio = "";
privatestaticbool Recursiu = false;
privatestaticbool Force = false;
privatestaticstring Pwd = "";
privatestaticstring CarpetaAProcessar = "";
privatestaticbool Creacio_de_cero = false;
privatestaticbool Continua = false;
staticvoid 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);
}
}
privatestaticvoid 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);
}
}
}
privatestaticvoid 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);
}
}
}
}
privatestaticvoid 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();
}
}
}
/// <summary>/// Genera una clau de 32 bytes, 256 bits/// </summary>/// <param name="pPwd">Valor del que es genera el hash 256</param>/// <returns></returns>privatestaticbyte[] PwdBytes(string pPwd)
{
SHA256Managed SHA2 = new SHA256Managed();
UTF8Encoding encoder = new UTF8Encoding();
byte[] bodyStringBytes = encoder.GetBytes(pPwd);
byte[] pwdBytes = SHA2.ComputeHash(bodyStringBytes);
return pwdBytes;
}
privatestaticbyte[] IVBytes(string pPwd, string FileName)
{
SHA256Managed SHA2 = new SHA256Managed();
UTF8Encoding encoder = new UTF8Encoding();
byte[] bodyStringBytes = encoder.GetBytes(pPwd + FileName);
byte[] IV = newbyte[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;
}
privatestatic clsDadesDesxifratRetorn obre(string pPath)
{
//El filtre *.xxx evita agafar fitxers que no toquenstring[] 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;
}
privatestatic 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;
}
privatestaticbool PotProcessarFitxer(string Fitxer)
{
string NomEnMinuscules = Fitxer.ToLower();
if (!NomEnMinuscules.Contains("opensesame.exe")
&& !NomEnMinuscules.Contains("hasher.xml")
&& !NomEnMinuscules.Contains("hasher.exe")
&& !NomEnMinuscules.Contains("locker.xml"))
{
returntrue;
}
else
{
returnfalse;
}
}
privatestaticvoid CryptFile(string inputFile, byte[] passwordBytes, long TamanyFitxer)
{
//create output file name
FileStream fsCrypt = new FileStream(inputFile + ".xxx", FileMode.Create);
string NomFitxerSenseRutaNiUnitat = Path.GetFileName(inputFile);
//Set Rijndael symmetric encryption algorithm
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;
//Cipher modes: http://security.stackexchange.com/questions/52665/which-is-the-best-cipher-mode-and-padding-mode-for-aes-encryption
AES.Mode = CipherMode.CFB;
CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write);
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
//create a buffer (1mb) so only this amount will allocate in the memory and not the whole filebyte[] buffer = newbyte[4194304];
int read;
if (TamanyFitxer < 4194304) //4MB
{
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();
}
//close up
fsIn.Close();
cs.Close();
fsCrypt.Close();
}
privatestaticvoid DeCryptFile(string inputFile, byte[] passwordBytes, long TamanyFitxer)
{
//todo:// - create error message on wrong password// - on cancel: close and delete file// - on wrong password: close and delete file!// - create a better filen name// - could be check md5 hash on the files but it make this slowstring 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;
/*
https://docs.microsoft.com/es-es/archive/blogs/shawnfa/the-differences-between-rijndael-and-aes
Since RijndaelManaged is an implementation of Rijndael, it will allow you to select different block sizes
(although both block and key sizes must be either 128, 192, or 256 bits. 160 and 224 bit are not supported).
By selecting a block size which is not 128 bits however, RijndaelManaged will not be able to interoperate
with an AES implementation ... since the block sizes will not match on either end of the communication.
One other interesting quirk of the RijndaelManaged implementation is that it will adjust block size
to match the feedback size in CFB mode.
This means that if you use CFB and a block size of 128 bits,
but a feedback size which is not 128 bits you again will not be compatible with AES.
Generally this does not affect many people, since the most common cipher mode to use is CBC.
Essentially, if you want to use RijndaelManaged as AES you need to make sure that:
The block size is set to 128 bits
You are not using CFB mode, or if you are the feedback size is also 128 bits
*/
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 = newbyte[4194304];
if (TamanyFitxer < 4194304) //4MB
{
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();
}
privatestaticstring 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 = newbyte[3];
ICryptoTransform EncDec = null;
#endregion
//Les claus AES poden ser 128, 192 o 256 bits
AES.KeySize = 256;
AES.Key = PwdBytes(Pwd);
AES.IV = IV;
AES.Mode = CipherMode.ECB;
AES.Padding = PaddingMode.Zeros;
OrigenBytes = ConvertHexStringToByteArray("00000000000000000000000000000000");
Encrypted = newbyte[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";
}
}
publicstaticstring ConvertByteArrayToHexString(byte[] ba)
{
StringBuilder sb = newStringBuilder(ba.Length * 2);
foreach (byte b in ba)
{
sb.AppendFormat("{0:x2}", b);
}
return sb.ToString().ToUpper();
}
publicstaticbyte[] SubArray(byte[] data, int index, int length)
{
byte[] result = newbyte[length];
Array.Copy(data, index, result, 0, length);
return result;
}
publicstaticbyte[] ConvertHexStringToByteArray(string hexString)
{
if (hexString.Length % 2 != 0)
{
thrownew 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 = newbyte[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;
}
publicstaticstring ObtenirData()
{
returnDateTime.Now.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture);
}
publicstaticstring ObtenirData(DateTime data)
{
return data.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture);
}
publicstaticstring 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;
}
privatestaticvoid 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 = newDictionary<string, clsFitxer>();
clsFitxer FitxerActualitzat = null;
DicFitxers = CarregaHashos(pPath);
DirectoryInfo dir = new DirectoryInfo(pPath);
FileInfo[] Fitxers = dir.GetFiles();
Console.WriteLine(ObtenirData() + " - Processant " + pPath);
//Comprovar que tots els fitxers del fitxer de hashos estan al disc, treure els que no estanforeach (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);
}
}
//Comprovar que els fitxers de la carpeta estan, afegir els nousforeach (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);
}
}
}
publicstaticvoid 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 = newDictionary<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);
}
}
}
publicstaticvoid Save(string pPath, Dictionary<string, clsFitxer> DicFitxers)
{
XmlDocument Doc = newXmlDocument();
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");
}
publicstatic 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) //5 GB
{
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;
}
privatestatic 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;
}
publicstaticDictionary<string, clsFitxer> CarregaHashos(string pPath)
{
XmlDocument Doc = newXmlDocument();
XmlNode Fitxers;
XmlNodeList llistaDeFitxer;
XmlNode Nom;
XmlNode Hash;
XmlNode DataCreacio;
XmlNode DataVerificacio;
XmlNode Estat;
XmlNode MidaEnBytes;
clsFitxer objFitxer = null;
Dictionary<string, clsFitxer> DicFitxers = newDictionary<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:
Com un borreguet més de les masses he anat a veure aquesta pelic. El fet és que la peli no m'ha entussiasmat però tampoc m'ha decepcionat excessivament. Ja es sap que tot depen de les expectatives, i clar, les anteriors eren "taaaaaan bones" [sarcastic mode off], aleshores tot el que superi minimament el passat ja es pot donar com acceptable.
[Spoilers] La Rey segueix entrenant per ser Jedi, quan un missatge arriba conforme l'antic emperador galactic Palpatine és viu (aquell que liquiden a la VI peli o així) i clar, cal anar a liquidar-lo altra cop.
En una altra banda en Kylo es reuneix amb l'emperador al planeta Hexegol, que està ocult a la zona inexplorada. Allí li diu que ha construit d'amagat 10.000 destructors amb la capacitat de destruir planetes. És un moment una mica WTF, perque si ho penses després, val ara l'arma dels dolents no és una mega-estació orbital, ni un mega-planeta-destructor-gegant... Només pensar la base industrial per fabricar 10K destructors, les tripulacions, que fan mentre estan aparcats?... Que hem desvio. Total que l'emperador li diu a en Kylo que mati la Rey a canvi dels 10K destructors.
Van rebotan d'aqui cap allí, fins a la batalleta final, on sense cap ajut, els rebels es llancen contra els 10K destructors, sense reforços ni res, sent una petita flota. Però han llançat un missatge a la Galaxia perque vinguin a ajudar-los.
Al final, els coleguis rebels també venen, i clar ataquen el punt feble de la flota, una única antena que permet als destructors sortir de l'atmosfera del planeta. Perque Hexegol és un planeta força hostil (ideal per construir 10K destructors... WTF?), resumint que se la carreguen tota. De mentres la lluita a la superficie està entre el Kylo (que ara és bo), la Rey vs. el Palpatine segueix. El Palpatine vol que la Rey, que és la seva neta, el liquidi per transferir la seva ànima a ella (juntament amb els Lords Sith anteriors). Però al final el Palpatine decideix xuclar l'energia vital (a lo LifeForce) de la Rey i del Ben Solo (ex-Kylo Ren) i rejuvenir-se. La Rey amb l'energia dels anteriors Jedi resisteix i liquida al Palpatine, però també mor. En Ben Solo la resuscita i mor al cedir-li tota la seva energia vital. I apa celebració final i tal. El que no queda clar és si hi ha una nova república o que, o si hi haurà nous Jedi...[/Spoilers]
Critiques moltes, però no deixa de ser una Star Wars, no dolenta del tot. És entretinguda i ja compleix amb el seu objectiu, entretenir. Approved!
En Cixin Liu va escriure fa temps una sèrie de contes SciFi curts, el primer d'ells es diu "La tierra errante" i per això el títul. Però de fet són uns quants relats curts, tots bastant apocaliptics, amb aires moralitzants sobre temes de sobrepoblació, contaminació, repartició de la riquesa... No cal fer una recopilació de tots els relats però en general estàn força bé, i si hi ha algun que fluixeja, al ser curt doncs no cansa. Recomanat!
El Black Friday és el que té. A més davant la previsió de que per Nadal caigui poca cosa, el petit egoista en mi va començar a treballar. I clar, amb l'excusa de trobar una super oferta... a 350 lerus una RTX 2070 pos venga. La meva veterana de mil batalles 970GTX ja donava simptomes de fatiga a 2K (la resolució del meu monitor). A més a més del molt necessari suport per H265 clar. Dit i fet, ja la tinc posada al PC. Aquest cop no he arrancat el bus PCI-Express de la gràfica al treure l'antiga.