I'm moving from C# to Java and can't seem to find any information on this. I'm trying to read if a file using hex, in Java I use...
String s = Integer.toHexString(hexIn);
if(s.length() < 2){
s = "0" + Integer.toHexString(hexIn);
}
As I'm sure you know thats so if the byte read in is one characater long it adds a zero to make it hex, I wanna do the same thing for c# so far i have...
StreamReader reader = new StreamReader(fileDirectory);
long stickNoteLength = fileDirectory.Length;
int hexIn;
String hex = "";
for (int i = 0; (hexIn = reader.Read()) != -1; i++)
{
}
Now I'm stuck, sorry if this is a simple question and thanks for you help :)
string hex = String.Format("{0:X2}", hexIn);
With this formatting mask you will get for numbers from 0 to 32 (for example):
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
I have added 2 (0:X2) because you mentioned that you are reading bytes.
Note, that for representing hex numbers also will be correct to add 0x at the string beginning:
string hex = String.Format("0x{0:X2}", hexIn);
Try this
hex = hexIn.ToString("X");
or
hex = Convert.ToString(hexIn,16);
Related
I am using the SDS011 laser dust sensor and want to read the data in a Windows forms Application.
I get Hex Data. Example: AA C0 D4 04 3A 0A A1 60 1D AB
now the fourth and the third pair represent the PM2.5 value, in this example: 04D4 -> 1236 -> 123,6 ug/m^3
Could you please help me write a code for reading in the hex data and calculating the PM2.5 value?
Thanks.
If the data is coming as a string then it's simple as:
string inputData = "AA C0 D4 04 3A 0A A1 60 1D AB";
var inputDataSplit = inputData.Split(' ');
// Concatenate the fourth and the third string, and convert it to integer with base 16 (hex)
int pmValue = Convert.ToInt32(inputDataSplit[3] + inputDataSplit[2], 16);
// 1236
Console.Write(pmValue);
My real aim is to DateTime.Parse a date string from Shell32 GetDetailsOf Extended date field.
While furthering my debuging, I simply created a string that appears the same and DateTime is able to parse it. When I view the 2 strings in Memory, they appear different.
The first few Bytes only.....
s > 4c 22 2e 63 16 00 00 00 0e 20 39 00 2f 00 0e 20 35 00 2f
q > 4c 22 2e 63 11 00 00 00 39 00 2f 00 35 00 2f 00 32 00 30
Is there a way to format the string so that I am able to parse it with DateTime.Parse?
Shell32.Shell shell = new Shell32.Shell();
Shell32.Folder objFolder;
objFolder = shell.NameSpace(folder);
int i = 0;
foreach (Shell32.FolderItem2 item in objFolder.Items())
{
if (item.Type == "Windows Recorded TV Show")
{
mediaArray[i, 0] = objFolder.GetDetailsOf(item, 21); // serName
mediaArray[i, 1] = objFolder.GetDetailsOf(item, 254); // epName
mediaArray[i, 2] = objFolder.GetDetailsOf(item, 259); // desc
mediaArray[i, 3] = objFolder.GetDetailsOf(item, 258); // broad Date
DateTime dateValue;
CultureInfo culture;
DateTimeStyles styles;
styles = DateTimeStyles.AssumeLocal;
culture = CultureInfo.CreateSpecificCulture("en-US");
string s = mediaArray[i, 3].Normalize(); // Guessing this string isn't ASCII?
string q = "9/5/2014 12:00 AM";
if (s == q) { MessageBox.Show("They are the same."); } // Never Entered. ):
MessageBox.Show(s+"\n"+q); // They appear exactly the same!
dateValue = DateTime.Parse(q, culture, styles); // parses correctly
dateValue = DateTime.Parse(s, culture, styles); // fails at runtime
i++;
}
}
How can I extract the date from the "Media Created" column of a video file?
Eh, I found the answer here..
I had been searching since yesterday evening and when I finally post the question, I find the answer within 30 min.
Apparently the characters (char)8206 (char)8207 exist in the string s of GetDetailsOf. These characters appear invisible when I MessageBox.Show() them but never the less removing them resolved my issue.
// These are the characters that are not allowing me to parse into a DateTime
char[] charactersToRemove = new char[]
{
(char)8206,
(char)8207
};
// Removing the suspect characters
foreach (char c in charactersToRemove)
value = value.Replace((c).ToString(), "").Trim();
I am aware of the difference between == and String.Equals. But I was specifically using == to debug the problem.
I found the chars 8206 and 8207 by trying to remove them with the help of another post. Does anyone care to say how I could have found these invisible characters while debugging?
I basically have the same problem as in this question, but I'm having trouble filling in the apparently trivial parts left out from the accepted answer. I'm doing this in C# with Mono.
I have a CA root certificate, and from that I can get a byte[] holding a public key. I then get an untrusted certificate I need to verify. From what I understand, RSACryptoServiceProvider.VerifyData should do the trick, but first I need to set RSAParameters with the modulus and exponent from the public key.
(Edit: The following repeats some things already apparent from the question I linked to above.)
The piece of code that should do what I need and validate a server's certificate with a root certificate I trust is as follows:
RSACryptoServiceProvider publicKey = new RSACryptoServiceProvider();
RSAParameters publicKeyParams = new RSAParameters();
publicKeyParams.Modulus = GetPublicKeyModulus();
publicKeyParams.Exponent = GetPublicKeyExponent();
publicKey.ImportParameters(publicKeyParams);
return publicKey.VerifyData(SignedValue(), CryptoConfig.MapNameToOID("SHA1"), Signature());
My problem is the contents of the GetPublicKeyModulus() and GetPublicKeyExponent(). In the accepted answer they are left out as apparently trivial, with just a comment saying the modulus is the value of the first TLV in my public key, and the exponent is the second TLV in the public key. I don't fully understand what that means.
byte[] GetPublicKeyExponent()
{
// The value of the second TLV in your Public Key
}
byte[] GetPublicKeyModulus()
{
// The value of the first TLV in your Public Key
}
byte[] SignedValue()
{
// The first TLV in your Ceritificate
}
byte[] Signature()
{
// The value of the third TLV in your Certificate
}
My question is what do these "first TLV"/"second TLV" exactly mean and how do I get those values from the byte array I have?
From what I understand, TLV stands for type-length-value. So if I have it correct, first bits of the byte array containing the public key have information about how many bits the modulus data is. Using that information I'm supposed to copy that amount of bits from the public key into another array, and set RSAParameters.Modulus to that value. After the modulus in the public key comes the exponent, and I should do the same operation with that. But I can't find information about in how many bits and in what format is the "TL" part of a TLV in the public key data contained.
I found information elsewhere saying the modulus is the first 1024 bits in the public key, and the exponent is the remainder, but that gave me an error about size when copying data between the byte arrays.
At the moment my code that I've been forming based on the accepted answer in the question I linked looks basically like this:
using System;
using System.Net;
using System.Security.Cryptography.X509Certificates;
X509Certificate2 trustedRootCertificate = new X509Certificate2(X509Certificate2.CreateFromCertFile(filename));
ServicePointManager.ServerCertificateValidationCallback = ValidateServerCertificate;
.
.
public bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
.
.
byte[] publicKeyBytes = trustedRootCertificate.GetPublicKey();
byte[] modulusData = // The value of the first TLV in the Public Key??
byte[] exponentData = // The value of the second TLV in the Public Key??
RSAParameters publicKeyParams = new RSAParameters();
publicKeyParams.Modulus = modulusData;
publicKeyParams.Exponent = exponentData;
RSACryptoServiceProvider publicKey = new RSACryptoServiceProvider();
publicKey.ImportParameters(publicKeyParams);
byte[] certificateData = certificate.GetRawCertData();
byte[] signedValue = // The first TLV in the certificate??
byte[] encryptedSignature = // The third TLV in the certificate??
return publicKey.VerifyData(certificateData, HashAlgorithm.Create("SHA1"), encryptedSignature);
}
Or should I be using certificateData (the return value of certificate.GetRawCertData()) in the VerifyData call?
Elsewhere I've found that the encrypted signature part is the last 256 bits in the certificateData, I'm not sure if that's the same as "the third TLV in the certificate". If not, I'd be doing
byte[] certificateData = certificate.GetRawCertData();
byte[] encryptedSignature = new byte[256];
System.Array.Copy(certificateData, certificateData.Length - 256, encryptedSignature, 0, 256);
and then using encryptedSignature as the last parameter in the VerifyData call.
Instead of all this TLV business I've also tried simply
RSACryptoServiceProvider publicKey = trustedRootCertificate.PublicKey.Key as RSACryptoServiceProvider;
as the person in the question I linked to above, but using this the VerifyData call then returned false when I thought it shouldn't. The certificate the application gets from the server has trustedRootCertificate as its root cert, I should be able to do this with that, correct? The root's public key should be able to verify the server's cert?
It's very much possible I just have the very basics of certificate verification wrong from the start. If that's not the case, then my question is how do I get these values
// The value of the second TLV in your Public Key
..
// The value of the first TLV in your Public Key
from the public key of the trusted root cert I have.
Edit: I've also verified that the root certificate loaded from the file and the certificate the app gets from the server are what they're supposed to be by printing out their information, so the problem is not at least in the certificates being wrong. I just don't know how to use them correctly.
Lets say that you encountered with BIT STRING type containing the following Length - Value::
03(T - BIT STRING)
82(Read next 2 Bytes for actual Length)
01 0F(Actual Length of whole BIT STRING)
---BIT STRING Value Starts Here---
00(First Byte Of BIT STRING specifies the number of bits left unused in the final byte of BIT STRING which in this case is 0)
30(T - SEQUENCE)
82(Read next 2 Bytes for actual Length)
01 0A(Actual Length of whole SEQUENCE)
---SEQUENCE Value Starts Here---
02(T - INTEGER)
82(Read next 2 Bytes for actual Length)
01 01(Actual Length of whole INTEGER)
(Value starts from here till "Actual Length of whole INTEGER above")
---INTEGER Value Starts Here---
---Exponent Starts Here---
00 A9 CA B2 A4 CC CD 20 AF 0A
7D 89 AC 87 75 F0 B4 4E F1 DF C1 0F BF 67 61 BD
A3 64 1C DA BB F9 CA 33 AB 84 30 89 58 7E 8C DB
6B DD 36 9E 0F BF D1 EC 78 F2 77 A6 7E 6F 3C BF
93 AF 0D BA 68 F4 6C 94 CA BD 52 2D AB 48 3D F5
B6 D5 5D 5F 1B 02 9F FA 2F 6B 1E A4 F7 A3 9A A6
1A C8 02 E1 7F 4C 52 E3 0E 60 EC 40 1C 7E B9 0D
DE 3F C7 B4 DF 87 BD 5F 7A 6A 31 2E 03 99 81 13
A8 47 20 CE 31 73 0D 57 2D CD 78 34 33 95 12 99
12 B9 DE 68 2F AA E6 E3 C2 8A 8C 2A C3 8B 21 87
66 BD 83 58 57 6F 75 BF 3C AA 26 87 5D CA 10 15
3C 9F 84 EA 54 C1 0A 6E C4 FE C5 4A DD B9 07 11
97 22 7C DB 3E 27 D1 1E 78 EC 9F 31 C9 F1 E6 22
19 DB C4 B3 47 43 9A 1A 5F A0 1E 90 E4 5E F5 EE
7C F1 7D AB 62 01 8F F5 4D 0B DE D0 22 56 A8 95
CD AE 88 76 AE EE BA 0D F3 E4 4D D9 A0 FB 68 A0
AE 14 3B B3 87 C1 BB
-----Exponent Ends Here----
---INTEGER Value Ends Here---
02(T - INTEGER)
03(Actual Length cuz 8th Bit Not Set here, so this byte shows the actual length)
---INTEGER Value Starts Here---
----Mod Starts Here---
01 00 01
---Mod Ends Here---
---INTEGER Value Ends Here---
---SEQUENCE Value Ends Here---
---BIT STRING Value Ends Here---
You might want to read ASN.1 Format
With RSACryptoServiceProvider:
X509Certificate2 certificate = Certificate.CreateFromBase64String(stringCert);
RSACryptoServiceProvider key = certificate.PublicKey.Key as RSACryptoServiceProvider;
if(key != null)
{
RSAParameters parameters = key.ExportParameters(false);
byte[] expoenet = parameters.Exponent;
byte[] modulus = parameters.Modulus;
}
https://social.msdn.microsoft.com/Forums/vstudio/en-US/4282dda1-4803-435a-b63a-65e2d5ac9941/get-modulus-exponent-from-certificate-public-key?forum=netfxbcl
var numberFormat = new NumberFormatInfo();
numberFormat.NumberDecimalSeparator = ".";
numberFormat.NumberDecimalDigits = 2;
decimal a = 10.00M;
decimal b = 10M;
Console.WriteLine(a.ToString(numberFormat));
Console.WriteLine(b.ToString(numberFormat));
Console.WriteLine(a == b ? "True": "False");
In console:
10.00
10
True
Why is it different? More important, how do I call ToString() to ensure same output no matter how a variable is initialized?
The question of how to make it output consistently has been answered, but here is why they output differently in the first place:
A decimal value contains, internally, fields for a scale and a coefficient. In the case of 10M, the value encoded has a coefficient of 10 and a scale of 0:
10M = 10 * 10^0
In the case of 10.00M, the value encoded has a coefficient of 1000 and a scale of 2:
10.00M = 1000 * 10^(-2)
You can sort of see this by inspecting the values in-memory:
unsafe
{
fixed (decimal* array = new decimal[2])
{
array[0] = 10M;
array[1] = 10.00M;
byte* ptr = (byte*)array;
Console.Write("10M: ");
for (int i = 0; i < 16; i++)
Console.Write(ptr[i].ToString("X2") + " ");
Console.WriteLine("");
Console.Write("10.00M: ");
for (int i = 16; i < 32; i++)
Console.Write(ptr[i].ToString("X2") + " ");
}
}
Outputs
10M: 00 00 00 00 00 00 00 00 0A 00 00 00 00 00 00 00
10.00M: 00 00 02 00 00 00 00 00 E8 03 00 00 00 00 00 00
(0xA is 10 in hex, and 0x3E8 is 1000 in hex)
This behaviour is outlined in section 2.4.4.3 of the C# spec:
A real literal suffixed by M or m is of type decimal. For example, the literals 1m, 1.5m, 1e10m, and 123.456M are all of type decimal. This literal is converted to a decimal value by taking the exact value, and, if necessary, rounding to the nearest representable value using banker's rounding (ยง4.1.7). Any scale apparent in the literal is preserved unless the value is rounded or the value is zero (in which latter case the sign and scale will be 0). Hence, the literal 2.900m will be parsed to form the decimal with sign 0, coefficient 2900, and scale 3.
The NumberDecimalDigits property is used with the "F" and "N" standard format strings, not the ToString method called without a format string.
You can use:
Console.WriteLine(a.ToString("N", numberFormat));
Try this:
Console.WriteLine(String.Format("{0:0.00}", a));
Console.WriteLine(String.Format("{0:0.00}", b));
The output will have always 2 decimal cases. More examples here:
http://www.csharp-examples.net/string-format-double/
I have following string of bytes
17 80 41 00 01 00 01 00 08 00 44 61 72 65 46 61 74 65 01 00 00 00 01 00 03 00 01 00 09 00 43 68 61 6E 6E 65 6C 2D 31 00 00 02 00 09 00 43 68 61 6E 6E 65 6C 2D 32 65 00 03 00 09 00 43 68 61 6E 6E 65 6C 2D 33 65 00
What is the best way to take it as input from user and make it into byte array?
Try:
string text = ...
byte[] bytes = text.Split()
.Select(t => byte.Parse(t, NumberStyles.AllowHexSpecifier))
.ToArray();
If you want to only split on the space-character (rather than any whitespace) use Split (' ').
If the user is inputting it into the command line just like that, do this:
string input = GetInput(); // this is where you get the input
string[] numbs = input.Split(' ');
byte[] array = new byte[numbs.Length];
int i = 0;
foreach (var numb in numbs)
{
array[i++] = byte.Parse(numb, NumberStyles.HexNumber);
}
You can use the Parse method in System.Byte to parse the individual hax pairs:
// Get the string from the user
string s=Console.ReadLine();
// Convert to a byte array
byte[] sBytes=s.Split(new char[] {' '})
.Select(hexChar => byte.Parse(hexChar,NumberStyles.HexNumber))
.ToArray();
// *** Test code follows ***
// Display the bytes (optional), to verify that the conversion worked
StringBuilder hexString=new StringBuilder(sBytes.Length*3);
foreach (byte b in sBytes)
{
// Separate hex pairs with a space
if (hexString.Length>0)
hexString.Append(' ');
// Append next hex pair (i.e., formatted byte)
hexString.AppendFormat("{0:x2}",b);
}
Console.WriteLine(hexString);