Does anyone know how can I hash the user's password using the salt key provided by the ASP .NET Membership?
I'm developing a C++ Linux application and I have only access to the SQL Server.
Thanks,
Here is the encoding algorithm used by ASP.Net Membership which is written in C#.
It uses System.Security, so you might want to look at MONO if you want to run on Lunix.
Note: I'm not familiar with MONO.
private string EncodePassword(string pass, int passwordFormat, string salt)
{
if (passwordFormat == 0) // MembershipPasswordFormat.Clear
return pass;
byte[] bIn = Encoding.Unicode.GetBytes(pass);
byte[] bSalt = Convert.FromBase64String(salt);
byte[] bRet = null;
if (passwordFormat == 1)
{ // MembershipPasswordFormat.Hashed
HashAlgorithm hm = GetHashAlgorithm();
if (hm is KeyedHashAlgorithm)
{
KeyedHashAlgorithm kha = (KeyedHashAlgorithm)hm;
if (kha.Key.Length == bSalt.Length)
{
kha.Key = bSalt;
}
else if (kha.Key.Length < bSalt.Length)
{
byte[] bKey = new byte[kha.Key.Length];
Buffer.BlockCopy(bSalt, 0, bKey, 0, bKey.Length);
kha.Key = bKey;
}
else
{
byte[] bKey = new byte[kha.Key.Length];
for (int iter = 0; iter < bKey.Length; )
{
int len = Math.Min(bSalt.Length, bKey.Length - iter);
Buffer.BlockCopy(bSalt, 0, bKey, iter, len);
iter += len;
}
kha.Key = bKey;
}
bRet = kha.ComputeHash(bIn);
}
else
{
byte[] bAll = new byte[bSalt.Length + bIn.Length];
Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
bRet = hm.ComputeHash(bAll);
}
}
else
{
byte[] bAll = new byte[bSalt.Length + bIn.Length];
Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
bRet = EncryptPassword(bAll, _LegacyPasswordCompatibilityMode);
}
return Convert.ToBase64String(bRet);
}
private string GenerateSalt()
{
byte[] buf = new byte[SALT_SIZE];
(new RNGCryptoServiceProvider()).GetBytes(buf);
return Convert.ToBase64String(buf);
}
Related
1. About the problem
I'm trying to send data store in a array called UxbTx[64] to 2 Hid devices that have the same VendorID(VID) and ProductID(PID) but differ in SerialNum (this differnce help me to enumerate 2 devices) and connect to PC via Usb Hub . I have successfully recognized two device and use hid_write() to send data but just 1 device acting right with my data config. For example, i want to turn on 2 devices but device 1 ON whereas the device 2 still remain OFF.
2. What I have tried
At first I thought that I have failed to send to the second device but it not. I use res=hid_write() and it return 0 which means successfully send for both devices.
This is the code that i use:
static hid_device** id_device;
static int max_size;
int res;
struct device_info
{
wchar_t* serial_num;
int id;
};
std::vector<device_info> devEnum(unsigned short vendor_id, unsigned short product_id)
{
std::vector<device_info> device;
int count = 0, total = 0, res = 0,i=0;
hid_device_info* dev = NULL, * cur_dev = NULL;
hid_device* temp_handle = NULL;
std::vector<wchar_t*> string;
wchar_t wstr[MAX_STR], temp[MAX_STR];
device_info inf;
hid_enumerate(vendor_id, product_id);
res = hid_init();
dev = hid_enumerate(0x461, 0x20);
for (cur_dev = dev; cur_dev != NULL; cur_dev = cur_dev->next)
{
memcpy(temp, cur_dev->serial_number, MAX_STR);
wcsncpy(temp, cur_dev->serial_number, MAX_STR);
temp[MAX_STR - 1] = L'\0';
string.push_back(temp);
inf.serial_num = cur_dev->serial_number;
inf.id = count;
device.push_back(inf);
count++;
}
max_size = device.size();
return device;
}
int NhgIsOpen(wchar_t* Manufacturer, wchar_t* Product, wchar_t* SerialNumber, std::vector<device_info> devices) {
int length = devices.size();
int res = 0;
id_device = new hid_device * [length];
wchar_t KeyManufacturer[MAX_STR] = L"test";
wchar_t KeyProduct[MAX_STR] = L"device test";
for (int i = 0; i < length; i++)
{
id_device[i] = hid_open(0x123, 0x15, devices[i].serial_num);
if (!id_device[i])
return -2;
hid_set_nonblocking(id_device[i], 0);
res = hid_get_manufacturer_string(id_device[i], Manufacturer, MAX_STR);
if (wcscmp(Manufacturer, KeyManufacturer) != 0)
return -3; //Manufacturer not match
res = hid_get_product_string(id_device[i], Product, MAX_STR);
if (wcscmp(Product, KeyProduct) != 0)
return -4; // KeyProdeuct not match
}
return 0;
}
INT32 IoControl(UINT16 IoState, int axis_id) {
UINT8 UsbTx[64];
//clear TX buffer
std::fill_n(UsbTx, 64, 0);
//report byte
UsbTx[0] = 0x01;
//USB user define cmd
UsbTx[1] = 0x00;
UsbTx[2] = 0x15; // turn on device
UsbTx[11] = 0x00;
UsbTx[12] = (0xFF) & IoState;
res = hid_write(id_device[axis_id], UsbTx, 64);
if (res < 0)
return -5; //can't write
return 0;
}
3. Question
If i can enumerate 2 devices does it means i can talk to 2 devices simultaneously?
Does the Report ID in firmware is the problem? I mean does i have to re-config Report ID in the Descriptor of the device so they can read the data at the same time?
I have an issue while deploying contract in TRON network, where I am required to specify address in format that starts with 4.. or when I receive transactions history (here the api respond with 4.. addresses as well).
Therefore I have a question:
How to convert TRON address started with TLAXtqju7GKyqoP... to 419b6e043089843624c36f1e3b1e8572d189cbe170 and vice versa?
How to convert TRON address started with TLAXtqju7GKyqoP... to 419b6e043089843624c36f1e3b1e8572d189cbe170 and vice versa?
const TronWeb = require('tronweb');
const tronWeb = new TronWeb(
'http://127.0.0.1:9090',
'http://127.0.0.1:9090',
'http://127.0.0.1:9090',
'd6fbbf6eecffdb32172e391363a401f89617acb9dd01897b9fa180830a8a46b2',
);
Once you have the tronWeb object, then you can convert the addresses vice-versa by using tronWeb's address utility
For Example:
const addressInHexFormat = '414450cf8c8b6a8229b7f628e36b3a658e84441b6f';
const addressInBase58 = tronWeb.address.fromHex(addressInHexFormat);
> addressInBase58 = 'TGCRkw1Vq759FBCrwxkZGgqZbRX1WkBHSu'
const addressInHex = tronWeb.address.toHex(addressInBase58);
> addressInHex = '414450cf8c8b6a8229b7f628e36b3a658e84441b6f'
Note
The above tronWeb object is created by using Tron's Quickstart Docker container. In this way the addresses can be converted vice-versa.
You just should decode your base58Address from Base58. In result you will obtain addresschecksum, so you should remove last 4 bytes from result and obtain desired address.
address = 41||sha3[12,32): 415a523b449890854c8fc460ab602df9f31fe4293f
sha256_0 = sha256(address): 06672d677b33045c16d53dbfb1abda1902125cb3a7519dc2a6c202e3d38d3322
sha256_1 = sha256(sha256_0): 9b07d5619882ac91dbe59910499b6948eb3019fafc4f5d05d9ed589bb932a1b4
checkSum = sha256_1[0, 4): 9b07d561
addchecksum = address || checkSum: 415a523b449890854c8fc460ab602df9f31fe4293f9b07d561
base58Address = Base58(addchecksum): TJCnKsPa7y5okkXvQAidZBzqx3QyQ6sxMW
The address format is well explained in the relevant TRON documentation.
In Java code (based on wallet-cli):
public String tronHex(String base58) {
byte[] decoded = decode58(base58);
String hexString = decoded == null ? "" : org.spongycastle.util.encoders.Hex.toHexString(decoded);
return hexString;
}
private byte[] decode58(String input) {
byte[] decodeCheck = Base58.decode(input);
if (decodeCheck.length <= 4) {
return null;
}
byte[] decodeData = new byte[decodeCheck.length - 4];
System.arraycopy(decodeCheck, 0, decodeData, 0, decodeData.length);
byte[] hash0 = Sha256Hash.hash(decodeData);
byte[] hash1 = Sha256Hash.hash(hash0);
if (hash1[0] == decodeCheck[decodeData.length] &&
hash1[1] == decodeCheck[decodeData.length + 1] &&
hash1[2] == decodeCheck[decodeData.length + 2] &&
hash1[3] == decodeCheck[decodeData.length + 3]) {
return decodeData;
}
return null;
}
And the other way around:
public String hexStringTobBase58(String hexString) {
hexString = adjustHex(hexString);
byte[] decodedHex = hexString == null? new byte[0] : org.spongycastle.util.encoders.Hex.decode(hexString);
String base58 = encode58(decodedHex);
return base58;
}
private String adjustHex(String hexString) {
if (hexString.startsWith("0x")) {
hexString = "41" + hexString.substring(2);
}
if (hexString.length() % 2 == 1) {
hexString = "0" + hexString;
}
return hexString;
}
private String encode58(byte[] input) {
byte[] hash0 = Sha256Hash.hash(input);
byte[] hash1 = Sha256Hash.hash(hash0);
byte[] inputCheck = new byte[input.length + 4];
System.arraycopy(input, 0, inputCheck, 0, input.length);
System.arraycopy(hash1, 0, inputCheck, input.length, 4);
return Base58.encode(inputCheck);
}
Find class Base58 here, class Sha256Hash here and the required dependency to Spongy Castle here.
C# example:
public static string GetHex(this String str)
{
var sb = new StringBuilder();
var bytes = Base58.Bitcoin.Decode(str); // nuget https://www.nuget.org/packages/SimpleBase/
for (int i = 0; i < bytes.Length - 4; i++)
{
var t = bytes[i];
sb.Append(t.ToString("X2"));
}
return sb.ToString();
}
I use the following code to encrypt a string with a key, using the 3-DES algorithm:
private bool Encode(string input, out string output, byte[] k, bool isDOS7)
{
try
{
if (k.Length != 16)
{
throw new Exception("Wrong key size exception");
}
int length = input.Length % 8;
if (length != 0)
{
length = 8 - length;
for (int i = 0; i < length; i++)
{
input += " ";
}
}
TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
des.Mode = CipherMode.ECB;
des.Padding = PaddingMode.Zeros;
des.Key = k;
ICryptoTransform ic = des.CreateEncryptor();
byte[] bytePlainText = Encoding.Default.GetBytes(input);
MemoryStream ms = new MemoryStream();
CryptoStream cStream = new CryptoStream(ms,
ic,
CryptoStreamMode.Write);
cStream.Write(bytePlainText, 0, bytePlainText.Length);
cStream.FlushFinalBlock();
byte[] cipherTextBytes = ms.ToArray();
cStream.Close();
ms.Close();
output = Encoding.Default.GetString(cipherTextBytes);
}
catch (ArgumentException e)
{
output = e.Message;
//Log.Instance.WriteToEvent("Problem encoding, terminalID= "+objTerminalSecurity.TerminalID+" ,Error" + output, "Security", EventLogEntryType.Error);
return false;
}
return true;
}
I send the output parameter as is over to a WCF http-binding webservice, and I noticed that the actual encoded string looks different, it looks like there are some \t and \n but the charachters are about the same.
What is going on, why does the server get a different encoded string?
Usually cipher text is base64 encoded in an effort to be binary safe during transmission.
Also I would not use 3DES with ECB. That is awful, you must have copy pasted this from somewhere. Use AES with cbc mode and think about adding a cmac or hmac.
I am using Silverlight4 with java webervices in jsp page. I want to save an image to the server so trying to do this with java webservice. I am using below lines of code but output is damaged. I dont understand why. Please help me. This is really important for me. When i try to open 3mb jpeg file contains "Windows Photo Viewer cant open this picture because file appears to be damaged, corrupted or is too large."
Client Side COde
WriteableBitmap wb = new WriteableBitmap(bitmapImage);
byte[] bb = ToByteArray(wb);
public byte[] ToByteArray(WriteableBitmap bmp)
{
int[] p = bmp.Pixels;
int len = p.Length * 4;
byte[] result = new byte[len]; // ARGB
Buffer.BlockCopy(p, 0, result, 0, len);
return result;
}
WebService Code
#WebMethod(operationName = "saveImage")
public Boolean saveImage(#WebParam(name = "img")
byte[] img, #WebParam(name = "path")
String path) {
try{
FileOutputStream fos = new FileOutputStream("C:\\Users\\TheIntersect\\Desktop\\sharp_serializer_dll\\saved.jpg");
fos.write(img);
fos.close();
return true;
}
catch(Exception e){
return false;
}
}
I found my answer on forums.silverlight.net
It is very interesting when i try to call ReadFully(Stream) just after the Stream definition it works but when i call 10 lines of code later it returns all 0.
FUnction
public static byte[] ReadFully(Stream input)
{
byte[] buffer = new byte[input.Length];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
Fail Code
using (Stream str = opd.File.OpenRead())
{
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(str);
image.Tag = bitmapImage.UriSource.ToString();
image.Source = bitmapImage;
image.Width = width;
image.Height = height;
image.Stretch = Stretch.Uniform;
container.Child = image;
rtb.Selection.Insert(container);
ServiceReference1.webWordWebServiceClient s = new ServiceReference1.webWordWebServiceClient();
byte[] bb = ReadFully(str);
s.saveImageCompleted += new EventHandler<ServiceReference1.saveImageCompletedEventArgs>(s_saveImageCompleted);
s.saveImageAsync(bb, "gungorrrr");
}
Successfull Code
using (Stream str = opd.File.OpenRead())
{
byte[] bb = ReadFully(str);
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(str);
image.Tag = bitmapImage.UriSource.ToString();
image.Source = bitmapImage;
image.Width = width;
image.Height = height;
image.Stretch = Stretch.Uniform;
container.Child = image;
rtb.Selection.Insert(container);
ServiceReference1.webWordWebServiceClient s = new ServiceReference1.webWordWebServiceClient();
(bitmapImage);
s.saveImageCompleted += new EventHandler<ServiceReference1.saveImageCompletedEventArgs>(s_saveImageCompleted);
s.saveImageAsync(bb, "gungorrrr");
}
Link: http://forums.silverlight.net/forums/p/234126/576070.aspx#576070
I would like to know how to retrieve the list of users that are logged onto a Remote machine. I can do it with qwinsta /server:xxxx, but would like to do it in C#.
check out wmi in .net under system.management.
something like:
ConnectionOptions conn = new ConnectionOptions();
conn.Authority = "ntdlmdomain:NAMEOFDOMAIN";
conn.Username = "";
conn.Password = "";
ManagementScope ms = new ManagementScope(#"\\remotecomputer\root\cimv2", conn);
ms.Connect();
ObjectQuery qry = new ObjectQuery("select * from Win32_ComputerSystem");
ManagementObjectSearcher search = new ManagementObjectSearcher(ms, qry);
ManagementObjectCollection return = search.Get();
foreach (ManagementObject rec in return)
{
Console.WriteLine("Logged in user: " + rec["UserName"].ToString());
}
You may not need the ConnectionOptions...
I ended up using the qwinsta /server:server1 command from C# -- it was much easier
thanks Ken
All this checks all 8 servers at the same time -- I put the result in sql server
but you can do what ever you want
query_citrix.bat script
cd C:.......\bin\citrix_boxes
qwinsta -server:servername or ip > servername.txt
string sAppCitrixPath = Application.StartupPath.ToString() + "\\citrix_boxes\\";
//Run Script for current citrix boxes
Process proc = new Process();
ProcessStartInfo si = new ProcessStartInfo();
si.FileName = sAppCitrixPath + "query_citrix.bat";
proc.StartInfo = si;
proc.Start();
proc.WaitForExit();
int exitCode = proc.ExitCode;
proc.Close();
if (exitCode == 0)
{
//Execute update who is on the Citrix_Boxes Currently
DirectoryInfo dic = new DirectoryInfo(sAppCitrixPath);
FileInfo[] fic = dic.GetFiles("*.txt");
for (int i = 0; i < fic.Length; i++)
{
ParseQWinStaServerFile(fic[i].FullName.ToString(), fic[i].Name.ToString().ToUpper().Replace(".TXT",""));
File.Delete(fic[i].FullName.ToString());
}
}
private void ParseQWinStaServerFile(string sLocation,string sServer)
{
using (StreamReader sr = File.OpenText(sLocation))
{
string sRecord = String.Empty;
char[] cSep = new char[] {' '};
bool bFirst = true;
while ((sRecord = sr.ReadLine()) != null)
{
if (bFirst == false)
{
string[] items = sRecord.Split(cSep, StringSplitOptions.RemoveEmptyEntries);
//Make sure all columns are present on the split for valid records
if (sRecord.Substring(19, 1) != " ") // check position of user id to see if it's their
{
//Send the user id and server name where you want to.
//here is your user
id = items[1].ToString().ToLower().Trim()
//here is your server
};
}
else
{
bFirst = false;
}
}
}
}