C# MSSQL base64 insert and select. Data differs - c#

Im having a bit of a challenge here, I hope that some of you clever guys out there can guide/show me to a solution.
The code has been condensated/cut down a bit to ease you. Hense if a program error occurs, it is due to that.
The task of the program is to download a pdf from a URL, and save the PDF on a MS SQL server.
I can save it but it seems the data changes. E.g. The first byte from the downloaded PDF is 25h (correct) and when I save it in the database it changes to 1Fh (wrong).
I realise it must be the conversion between the download and saving, but unfortunately I cant make it work.
// This is where I suspect that my problem occurs.
byte[] myDataBuffer = client.DownloadData((new Uri(strFileUrlToDownload)));
Please excuse me if Im not clear in my writing. English isn't my first language.
Thanks in advance.
Script for create table and C# code below.
Script for creating the table on MS SQL server:
SET [ThePartikularDatabase]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[PDFTable](
[DokumentAID] [int] IDENTITY(1,1) NOT NULL,
[ident] [nchar](10) NOT NULL,
[AB] [nchar](10) NOT NULL,
[BI] [nchar](10) NOT NULL,
[dokumentType] [nchar](10) NOT NULL,
[base64] [varbinary](max) NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
Here comes the code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Web;
using System.Web.Script.Serialization;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using System.Web.UI;
using System.Text.RegularExpressions;
namespace test
{
class program
{
public static void DownloadData(string strFileUrlToDownload, WebClient client, string IV_ident, string IV_AB, string IV_BI, string IV_dokumentType)
{
// This function is made with inspiration from:
// http://www.c-sharpcorner.com/UploadFile/013102/save-and-read-pdf-file-using-sql-server-and-C-Sharp/
byte[] myDataBuffer = client.DownloadData((new Uri(strFileUrlToDownload)));
//string encodedText = Convert.ToBase64String(myDataBuffer);
//string decodedText = Encoding.UTF8.GetString(myDataBuffer);
// byte[] lars = Convert.ToByte(encodedText);
using (SqlConnection cn = new SqlConnection(GlobalVar.ConnectionString))
{
cn.Open();
using (SqlCommand cmd = new SqlCommand("INSERT INTO [Database].[dbo].[PDFTable] " + "(Ident, AB, BI, dokumentType, base64) values (#ident, #AB, #BI, #dokumentType, #data);", cn))
{
cmd.Parameters.Add("#data", myDataBuffer);
cmd.Parameters.Add("#Ident", ident);
cmd.Parameters.Add("#AB", IV_AB);
cmd.Parameters.Add("#BI", IV_BI);
cmd.Parameters.Add("#dokumentType", IV_dokumentType);
cmd.ExecuteNonQuery();
}
}
using (SqlConnection cn = new SqlConnection(GlobalVar.ConnectionString))
{
cn.Open();
using (SqlCommand cmd = new SqlCommand("SELECT [base64] FROM [Database].[dbo].[PDFTable] WHERE ident = " + IV_ident + " ;", cn))
{
using (SqlDataReader dr = cmd.ExecuteReader(System.Data.CommandBehavior.Default))
{
if (dr.Read())
{
byte[] fileData = (byte[])dr.GetValue(0);
using (System.IO.FileStream fs = new System.IO.FileStream("c:\\" + IV_ident + ".pdf", System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite))
{
using (System.IO.BinaryWriter bw = new System.IO.BinaryWriter(fs))
{
bw.Write(fileData);
bw.Close();
}
}
}
dr.Close();
}
}
}
}
public static void SaveMemoryStream(MemoryStream ms, string FileName)
{
FileStream outStream = File.OpenWrite(FileName);
ms.WriteTo(outStream);
outStream.Flush();
outStream.Close();
}
static void Main(string[] args)
{
int LI_start = 0;
int LI_slut = 0;
int LI_documentURL = 0;
string LS_ident = "";
string credentials = "Username:Password";
string url = "http://pdfurl.com/find;
CredentialCache mycache = new CredentialCache();
WebClient client = new WebClient();
client.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(credentials));
Regex regex = new Regex("");
try
{
/*
ident is fetched from our database. Code removed for simplicity..
*/
LS_ident = Convert.ToString(theRow["ident"]);
string LS_json = "{\"from\":0,\"size\":1,\"query\":{\"term\":{\"ident\":" + LS_ident + "}}}";
string LS_pdfURL = "";
string reply = client.UploadString(url, "POST", LS_json);
/********************************************************/
/* Regex ************************************************/
/*
URL for the pdf is taken from the reply with Regular expression.
*/
/* Regex ************************************************/
/********************************************************/
LS_pdfURL = "" + dokURL[i].Substring(LI_start, (LI_slut + 1 - LI_start)) + "pdf";
/*
LS_pdfURL now contains the correct path for the pdf.
I can manually download the pdf with the url. It works.
So far, so good.
*/
DownloadData(LS_pdfURL, client, LS_ident, "StartDato", "SlutDato", "Doktype");
/**/
//break;
}
thisConnection.Close();
}
catch (SqlException ex)
{
Console.WriteLine("Der skete en fejl: (get) {0}", ex.ToString());
}
/**/
}
}
}

Your problem has it's reason with the different encodings.
Base64 is meant to store binary data within string based containers such as XML or HTML by using a reduced set of characters. The encoded content is a string consisting of "secure characters" only and can be handled as any other string.
A Hex-String is a chain of bits. They are packed in groups of 4 and displayed with characters from 0 to 9 and A to F... Behind the scenes this is just a chain of bits, packed in groups and displayed as string of 16 characters. This needs - but only in characters! - more space than base64... as a bit-chain it needs less...
It is always necessary to think about: What type has my data and which is the appropriate type to store this?
You decided to place your base64 within a column of type VARCHAR(MAX). Seems to be a good choice. But I'd still prefer the VARBINARY(MAX) and do the base64 encoding when I need it.

Related

Nethereum EthECKey not working. Scripts are not compiled

If i add this line to my code then it refuses to compile!(This happens with All scripts in unity, even empty ones)
string publicKey = Nethereum.Signer.EthECKey.GetPublicAddress(privatekey);
Code:
using System.Collections;
using System;
using System.Collections.Generic;
using Nethereum.Util;
using UnityEngine;
using System.Threading.Tasks;
using Nethereum.Hex.HexConvertors.Extensions;
using Org.BouncyCastle.Crypto.Digests;
using System.Linq;
using System.Text;
using Nethereum.Util.Keccak;
using System.Numerics;
using System.Runtime.CompilerServices;
using Nethereum.RLP;
using Nethereum.Signer.Crypto;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Agreement;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
public class MianScript : MonoBehaviour
{
string chain = "ethereum";
string network = "rinkeby";
[SerializeField]
public string password;
public void OnClickBTN()
{
string privatekey = CreateAccount();
string publicKey = Nethereum.Signer.EthECKey.GetPublicAddress(privatekey);
Debug.Log("\nPrivate: " + privatekey + "\nPublicKey: " + publicKey);
}
public byte[] CalculateHash(byte[] value)
{
var digest = new KeccakDigest(256);
var output = new byte[digest.GetDigestSize()];
digest.BlockUpdate(value, 0, value.Length);
digest.DoFinal(output, 0);
return output;
}
public async Task<String> GetBalance(string chain1, string network1, string address1)
{
string balance = await EVM.BalanceOf(chain1, network1, address1);
return balance;
}
public static string CreateAccount()
{
System.Random random = new System.Random();
var bytes = new Byte[32];
random.NextBytes(bytes);
var hexArray = Array.ConvertAll(bytes, x => x.ToString("X2"));
var hexStr = String.Concat(hexArray);
return Convert.ToString(hexStr.ToLower());
}
}
Help pls!
I'm not using unity, C# either but it seems that GetPublicAddress() is not a static function but a class method.
So I think you need to do something like that:
// Creating an EthECKey instance
var key = new Nethereum.Signer.EthECKey(privateKey.HexToByteArray(), true);
// Getting the public Address
string publicKey = key.GetPublicAddress();
I simply checked examples from here.

Digital sign with sha256 with c#

here in Italy, we will need to digitally sign all invoices since January 2019.
I found a code that works well with sha-1, but I need to use sha256 as standard.
The code below, after successfully detect USB key, and ask me for the certificate to use try to sign "NomeFile" file After and output in "NomeFile".p7m, when the line
signedCms.ComputeSignature(signer,false);
runs, it happens:
1- if use sha-1 it asks me for the PIN and document is successfully created.
2- if use sha-256 don't ask for PIN and gives me Unknown error -1073741275
I read a lot of posts that are all old (2011-2014). Other people have the same problem and seem that Microsoft has some bug using sha256.
Now we are at end of 2018 and I tried this code in .net 4, 4.6.1 and 4.7.2 but the error is the same.
Somebody can tell me if Microsoft corrects the problem with sha256 and what could be this strange error? (-1073741275)
Error Stack
public String FirmaFile(String NomeFile, DateTime DataFirma, X509Certificate2 cert, out string RisFirma)
{
String NomeFirma = NomeFile + ".p7m";
RisFirma = "";
try
{
// content contiene il file da firmare
ContentInfo content = new ContentInfo((File.ReadAllBytes(NomeFile)));
// assegniamo content ad un oggetto di tipo SignedCms
SignedCms signedCms = new SignedCms(SubjectIdentifierType.IssuerAndSerialNumber, content, false);
// si instanzia un oggetto CmsSigner che espone i metodi di firma.
CmsSigner signer = new CmsSigner(cert);
signer.IncludeOption = X509IncludeOption.EndCertOnly;
//signer.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1");
signer.DigestAlgorithm = new Oid("SHA256");
signer.SignedAttributes.Add(new Pkcs9SigningTime(DataFirma));
try
{
// Viene calcolata la firma del file (in formato PKCS7)
signedCms.ComputeSignature(signer,false);
}
catch (CryptographicException CEx)
{
RisFirma = "Errore: " + CEx.Message + " Stack: " + CEx.StackTrace;
return RisFirma;
}
// si pone il file firmato in un array.
byte[] signature = signedCms.Encode();
File.WriteAllBytes(NomeFirma, signature);
RisFirma = "true";
}
catch (Exception Ex)
{
RisFirma = "Errore in FirmaFile: " + Ex.Message + " Stack: " + Ex.StackTrace;
}
return RisFirma;
}
NB: I tried 2 version of OID
signer.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1");
signer.DigestAlgorithm = new Oid("SHA256");
All 2 give the same error.
I USE an INFOCERT USB KEY with driver bit4id (https://www.bit4id.com/it/4identity/) that is contained in USB Drive.
The error and symptom seem to indicate that the CSP (Cryptographic Service Provider) which is doing the signing operation doesn't support SHA-2. If it's working in BouncyCastle then they are seemingly exporting the private key and re-importing it into their software provider.
In .NET 4.7.2 you could try the following:
...
try
{
// Viene calcolata la firma del file (in formato PKCS7)
signedCms.ComputeSignature(signer,false);
}
catch (CryptographicException CEx)
{
try
{
// Try re-importing the private key into a better CSP:
using (RSA tmpRsa = RSA.Create())
{
tmpRsa.ImportParameters(cert.GetRSAPrivateKey().ExportParameters(true));
using (X509Certificate2 tmpCertNoKey = new X509Certificate2(cert.RawData))
using (X509Certificate2 tmpCert = tmpCertNoKey.CopyWithPrivateKey(tmpRsa))
{
signer.Certificate = tmpCert;
signedCms.ComputeSignature(signer,false);
}
}
}
catch (CryptographicException)
{
// This is the original exception, not the inner one.
RisFirma = "Errore: " + CEx.Message + " Stack: " + CEx.StackTrace;
return RisFirma;
}
}
If the certificate is actually being loaded from a PFX file on the USB device, then the problem is that the PFX specifies to use an older software CSP which predated SHA-2. Getting the PFX regenerated to use the newest RSA CSP would also solve the problem.
use this:
private string podpisz(X509Certificate2 cert, string toSign)
{
string output = "";
try
{
RSACryptoServiceProvider csp = null;
csp = (RSACryptoServiceProvider)cert.PrivateKey;
// Hash the data
SHA256Managed sha256 = new SHA256Managed();
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] data = Encoding.Default.GetBytes(toSign);
byte[] hash = sha256.ComputeHash(data);
// Sign the hash
byte[] wynBin = csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));
output = Convert.ToBase64String(wynBin);
}
catch (Exception)
{
}
return output;
}
I found this in internet, I try it and incredibly it worked!
Anyway the solution is bit more complex.
You have to use BouncyCastle (https://www.bouncycastle.org/) library.
But not the version avaiable, but a version that was modified by on user on another forum.
The link to the bouncy castle library modified is:
http://www.mediafire.com/download/uc63d1hepqyuhee/bccrypto-net-1.7-src-ext_with_CADES-BES.zip
You have to use crypto.dll library found in bin\release and reference it in your project.
Theese are all using I have now, probably not all are required for this specified case:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
using System.Xml;
using System.IO;
using System.Collections;
using CryptoUpgNet.NonExportablePK;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Ess;
using Org.BouncyCastle.Cms;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
This is the function:
public byte[] FirmaFileBouncy(String NomeFile, X509Certificate2 cert, ref string RisFirma)
{
String NomeFirma = NomeFile + ".p7m";
try
{
SHA256Managed hashSha256 = new SHA256Managed();
byte[] certHash = hashSha256.ComputeHash(cert.RawData);
EssCertIDv2 essCert1 = new EssCertIDv2(new Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier("2.16.840.1.101.3.4.2.1"), certHash);
SigningCertificateV2 scv2 = new SigningCertificateV2(new EssCertIDv2[] { essCert1 });
Org.BouncyCastle.Asn1.Cms.Attribute CertHAttribute = new Org.BouncyCastle.Asn1.Cms.Attribute(Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers.IdAASigningCertificateV2, new DerSet(scv2));
Asn1EncodableVector v = new Asn1EncodableVector();
v.Add(CertHAttribute);
Org.BouncyCastle.Asn1.Cms.AttributeTable AT = new Org.BouncyCastle.Asn1.Cms.AttributeTable(v);
CmsSignedDataGenWithRsaCsp cms = new CmsSignedDataGenWithRsaCsp();
dynamic rsa = (RSACryptoServiceProvider)cert.PrivateKey;
Org.BouncyCastle.X509.X509Certificate certCopy = DotNetUtilities.FromX509Certificate(cert);
cms.MyAddSigner( rsa, certCopy, "1.2.840.113549.1.1.1", "2.16.840.1.101.3.4.2.1", AT, null);
ArrayList certList = new ArrayList();
certList.Add(certCopy);
Org.BouncyCastle.X509.Store.X509CollectionStoreParameters PP = new Org.BouncyCastle.X509.Store.X509CollectionStoreParameters(certList);
Org.BouncyCastle.X509.Store.IX509Store st1 = Org.BouncyCastle.X509.Store.X509StoreFactory.Create("CERTIFICATE/COLLECTION", PP);
cms.AddCertificates(st1);
//mi ricavo il file da firmare
FileInfo File__1 = new FileInfo(NomeFile);
CmsProcessableFile file__2 = new CmsProcessableFile(File__1);
CmsSignedData Firmato = cms.Generate(file__2, true);
byte[] Encoded = Firmato.GetEncoded();
File.WriteAllBytes(NomeFirma, Encoded);
RisFirma = "true";
return Encoded;
} catch (Exception ex) {
RisFirma = ex.ToString();
return null;
}
}
Edit: Using it repeatly with same certificate, it ask PIN only the first time. So is good to make multiple files at once with security standard active.
To Grzegorz:
The source file is 5k
The correct signed file (IT01234567890_FPA01_2.xml.p7m is 8k
The file saved with your routine adding a
File.WriteAllBytes("c:\\temp\\IT01234567890_FPA01.xml.p7m", wynBin);
after
byte[] wynBin = csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));
is only 1kb and is not reckognized by Dike.
Sign not reckognized
Difference between files

Getting Hash from command line arguments

I am trying to create a console or form where you would drag a file onto their respective .exe
The program would get that file and hash it, then set the clipboard text to the proviously generated hash.
This is my code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Windows.Forms;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string path = args[0];
StreamReader wer = new StreamReader(path.ToString());
wer.ReadToEnd();
string qwe = wer.ToString();
string ert = Hash(qwe);
string password = "~" + ert + "~";
Clipboard.SetText(password);
}
static public string Hash(string input)
{
MD5 md5 = MD5.Create();
byte[] inputBytes = Encoding.ASCII.GetBytes(input);
byte[] hash = md5.ComputeHash(inputBytes);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
sb.Append(hash[i].ToString("X2"));
}
return sb.ToString();
}
}
}
When I get the single .exe from the release, and drag a file onto it, I get some sort of threading error- I can't provide it because it is in the console, not in vb2010. Thanks for any help
Clipboard API uses OLE internally and thus can only be called on a STA thread. Unlike WinForms applications, console applications aren't using STA by default.
Add the [STAThread] attribute to Main:
[STAThread]
static void Main(string[] args)
{
...
Just do what the exception message told you to:
Unhandled Exception: System.Threading.ThreadStateException: Current thread must
be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it.
Cleaning up your program a bit:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Windows.Forms;
namespace HashToClipboard
{
class Program
{
[STAThread]
static void Main(string[] args)
{
string hexHash = Hash(args[0]);
string password = "~" + hexHash + "~";
Clipboard.SetText(password);
}
static public string Hash(string path)
{
using (var stream = File.OpenRead(path))
using (var hasher = MD5.Create())
{
byte[] hash = hasher.ComputeHash(stream);
string hexHash = BitConverter.ToString(hash).Replace("-", "");
return hexHash;
}
}
}
}
This has several advantages over your program:
It doesn't need to load the whole file into RAM at the same time
It returns the correct result if the file contains non-ASCII characters/bytes
It'd shorter and cleaner

How would I write this to a csv file in c#?

I hope someone can help me. I am a beginner at c# and programming in general and I'm trying to complete this program. Basically it looks in an XML file, grabs all of the occurrences of a specific tag and is supposed to write the File Names plus whatever is between any instances of these two tags. So far I've tried TextWriter, StreamWriter, FileStream and some others and nothing doing what I want. I realise this may be a stupid question but I'm a super noob and need help for my particular case. My code is as follows.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var files = from file in Directory.GetFiles("W:\\SRC\\hDefMl\\1.0\\Instrument_Files")
orderby file
ascending
select file;
StringBuilder sb_report = new StringBuilder();
string delimiter = ",";
sb_report.AppendLine(string.Join(delimiter, "Module", "Generator(s)"));
foreach (var file in files)
{
string filename = Path.GetFileNameWithoutExtension(file);
Console.WriteLine("The HDefML file for {0} contains these EEPROM Generators:", filename);
XDocument hdefml = XDocument.Load(file);
var GeneratorNames = from b in hdefml.Descendants("Generators")
select new
{
name = (string)b.Element("GeneratorName")
};
string description;
foreach (var generator in GeneratorNames)
{
Console.WriteLine(" GeneratorName is: {0}", generator.name);
sb_report.AppendLine(string.Join(delimiter, filename,
generator.name));
}
}
}
You should be able to just do something like this, if the string you have built with your string builder is formatted correctly.
static void WriteToCSV(string str, string path)
{
using (Stream stream = File.Create(path))
using (StreamWriter writer = new StreamWriter(stream))
{
writer.WriteLine(str);
}
}
try{
FileStream FS;
StreamWriter SW;
using (FS = new FileStream("HardCodedFileName.csv", FileMode.Append))
{
using (SW = new StreamWriter(FS))
{
foreach (var generator in GeneratorNames)
{
SW.WriteLine(string.Join(delimiter, filename,
generator.name));
}
}
}
}
catch (Exception e){
Console.Writeline(e.ToString());
}

Trouble getting groups out of Regex

The following code only returns "Good job!" How can I get the actual URLs out of it? I followed the tutorial on the site given, and I'm still having a bit trouble wrapping my head around it. Also, I imagine that this isn't the best way to go about regex (mixing regex with html). Is there a simple way to capture text based on it's CSS class?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
namespace Scraper
{
class Program
{
static void Main(string[] args)
{
string target = #"http://www.omegacoder.com/?p=58";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(target);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Regex URL = new Regex("(?:href=)(?<link>.*?)");
string line;
using (Stream responseStream = response.GetResponseStream())
using (StreamReader htmlStream = new StreamReader(responseStream))
while ((line = htmlStream.ReadLine()) != null){
Match m = URL.Match(line);
if (m.Success) {
Console.WriteLine("Good job! " + URL.Match(line) + m.Groups[0].Value + m.Groups[1].Value + m.Groups["link"]);
Console.ReadLine();
} else {
}
}
/* if (Regex.IsMatch(line, "XXXXX"))
Console.WriteLine(line);
} */
Console.ReadLine();
}
}
}
You should use (?:href=)(?<link>\S*)
\S matches a character that is not space

Categories

Resources