Verify private key in signed XML with public key - javascript

I use javascript to open CAPICOM store to choose certificate.
After that I export selected certificate, public key and private key of that certificate and put them in three hidden fields.
var privateKey = certificates.Item(1).PrivateKey;
var cert = certificates.Item(1);
var publicKey = cert.PublicKey().EncodedKey.Value
When signing xml I used:
To take certificate
Dim hideCertCapicom As String = Replace(HiddenCert.Value, " ", "+")
Dim certificate As New X509Certificate2(Convert.FromBase64String(hideCertCapicom))
For defining private key I used
Dim keyC As String = hideKey
Dim cspp As New CspParameters()
cspp.KeyContainerName = keyC
Dim tmpRsa As New RSACryptoServiceProvider(cspp)
tmpRsa.PersistKeyInCsp = True
This will successfully signed my xml.
For verifying xml I used:
Dim hidePublicKey As String = HiddenPublicKey.Value
Dim keyC As String = hidePublicKey
Dim cspp As New CspParameters()
cspp.KeyContainerName = keyC
Dim tmpRsa As New RSACryptoServiceProvider(cspp)
tmpRsa.PersistKeyInCsp = True
But this doesn't work. It works only if I use the private key again.
Is it good practice to sign and verify with the same private key or to do both with public key?

I was able to sign with private key and verify the signature with public key, and I want to share with you.
In SignXml() function I exported public key from private key:
Dim publicKey as String = tmpRsa.ToXmlString(False)
Then in the same function I call verifyXml() function:
Dim verifySign As Boolean
verifySign = VerifyXml(doc, publicKey)
In verifyXml() function I took public key on this way:
Public Function VerifyXml(Doc As XmlDocument, Key As String) As Boolean
Dim tmpRsa As New RSACryptoServiceProvider()
tmpRsa.FromXmlString(Key)
Dim signedXml As New SignedXml(Doc)
Dim nodeList As XmlNodeList = Doc.GetElementsByTagName("Signature")
If nodeList.Count <= 0 Then
Throw New CryptographicException("Verification failed: No Signature was found in the document.")
End If
If nodeList.Count >= 2 Then
Throw New CryptographicException("Verification failed: More that one signature was found for the document.")
End If
signedXml.LoadXml(DirectCast(nodeList(0), XmlElement))
Return signedXml.CheckSignature(tmpRsa)
End Function

Related

Not able to decrypt the encryptedValue using crypto

I am trying to decrypt a value (encrypted in des) coming from VB.
When I try to decrypt the encryptedValue using crypto in Javascript the output gives me an empty value.
I have attached how the encryption was done in VB.
HOW I AM TRYING TO DECRYPT IN JAVASCRIPT
var CryptoJS = require("crypto-js");
var key = "peekaboo";
var encryptedValue = "50AznWWn4fJI19T392wIv/ZysP/Ke3mB";
encryptedValue = CryptoJS.enc.Base64.parse(encryptedValue);
var data = CryptoJS.DES.decrypt(encryptedValue, key, { iv: "cbauthiv" });
const email = data.toString(CryptoJS.enc.Utf8);
console.log(email, "ORIGINAL TEXT");
THE WAY IT IS ENCRYPTED IN VB
Imports System.Security.Cryptography
Imports System.Text
Imports System.IO
Module Module1
Private Const ENCRYPTIONKEY As String = "peekaboo"
Sub Main()
Dim s As String = Encrypt("ditzymoose#outlook.com")
Dim r As String = Decrypt(s)
Console.ReadLine()
End Sub
Private Function Encrypt(stringToEncrypt As String) As String
Dim rng As New RNGCryptoServiceProvider
Dim byteArray() As Byte = New Byte(8) {}
Dim iv_value As String = "cbauthiv"
Dim key() As Byte = {}
Dim IV() As Byte = System.Text.Encoding.UTF8.GetBytes(Left(iv_value, 8))
key = System.Text.Encoding.UTF8.GetBytes(Left(ENCRYPTIONKEY, 8))
Dim des As New DESCryptoServiceProvider
rng.GetBytes(byteArray)
Dim Salt As String = BitConverter.ToString(byteArray)
Dim SaltedInput As String = Salt & "~" & stringToEncrypt
Dim inputByteArray() As Byte = Encoding.UTF8.GetBytes(stringToEncrypt)
Dim ms As New MemoryStream
Dim cs As New CryptoStream(ms, des.CreateEncryptor(key, IV), CryptoStreamMode.Write)
cs.Write(inputByteArray, 0, inputByteArray.Length)
cs.FlushFinalBlock()
Return Convert.ToBase64String(ms.ToArray())
End Function
End Module
The key and IV must be passed as WordArray. For the conversion the Utf8-Encoder has to be used, here.
Also, the ciphertext must be passed as a CipherParams object or alternatively Base64 encoded (which is then implicitly converted to a CipherParams object), here.
With these changes the ciphertext of the VB code can be successfully decrypted using the CryptoJS code:
var key = CryptoJS.enc.Utf8.parse("peekaboo");
var iv = CryptoJS.enc.Utf8.parse("cbauthiv");
var encryptedValue = "50AznWWn4fJI19T392wIv/ZysP/Ke3mB";
var data = CryptoJS.DES.decrypt(encryptedValue, key, {iv: iv});
var email = data.toString(CryptoJS.enc.Utf8);
console.log(email, "ORIGINAL TEXT");
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
Please note that DES is insecure (here) and was replaced by AES almost 20 years ago. Also insecure is a static IV. Instead, a random IV should be generated for each encryption.
Furthermore a password should not be used as key. If a password is to be used, the key should be derived from the password using a reliable key derivation function such as PBKDF2.

AES encryption in node resulting is different output compared to java

I'm trying to port the Java code for AES ECB encryption into node.js
The issues is that the output from java and node are not the same.
Here's the java code
public static final String DEFAULT_ENCODING = "UTF-8";
public static final String SEC_PROVIDER = "SunJCE";
public static final String AES_ALGORITHM = "AES";
public static final String RIJNDAEL_CIPHER = **"Rijndael/ECB/NoPadding"**;
public static final int **CIPHER_PAD_SIZE = 32**;
public static final String HEX_KEY = "3b6ce332ca3b6519eac769710f41ca5c";
public static String encryptData(String text, String hexKey) throws
Exception {
byte[] b1 = Hex.decodeHex(HEX_KEY.toCharArray());
SecretKey key = new SecretKeySpec(b1, AES_ALGORITHM);
Cipher cipher = Cipher.getInstance(RIJNDAEL_CIPHER, SEC_PROVIDER);
text = padRightToMod(text, CIPHER_PAD_SIZE);
byte[] buf = text.getBytes(DEFAULT_ENCODING);
cipher.init(Cipher.ENCRYPT_MODE, key);
buf = cipher.doFinal(buf);
String result = new String(Hex.encodeHex(buf));
result = result.toUpperCase();
return result;
}
// ensure block size of 32
public static String padRightToMod(String text, int mod) {
if (text == null || mod <= 0) {
return text;
}
final int len = text.length();
StringBuilder buf = new StringBuilder(512);
buf.append(text);
for (int i = len; i % mod > 0; i++) {
buf.append(" ");
}
String rs = buf.toString();
System.out.println(rs.length());
return rs;
}
// Call to the encrypt function
String encText = encryptData("Hello", HEX_KEY);
The result is CC0AC95B5FFD4758DBFA40F909C285F0F86A8F19ED1A12C1BFC098348A2AC683
And with this javascript code
crypto = require('crypto');
function encrypt(data,key) {
var cipher = crypto.createCipher('**aes-128-ecb**', key); //create aes cipher
var encrypted = cipher.update(data,'utf8', 'hex'); //output as hex
return encrypted;
}
function padRightTo32(str) // ensure block size of 32
{
len=str.length;
for(i=len; i%32>0; i++){
str=str +" ";
}
return str;
}
// call to encryption function
hexkey="3b6ce332ca3b6519eac769710f41ca5c"
encStr=encrypt(padRightTo32("Hello"),hexKey);
console.log(encStr);
The result is
1B928CF3C18D53BA5138DD1484D181939FD2B7BB2A17AE6A79664488B5C12652
==== Update ======
I tried https://github.com/Snack-X/rijndael-js implementaiton form github with this code
const Rijndael = require("./node_modules/node-rijndael-master");
function padRightTo32(str)
{
len=str.length;
for(i=len; i%32>0; i++){
str=str +" ";
}
console.log(str);
console.log(str.length);
return str;
}
let key = "3b6ce332ca3b6519eac769710f41ca5c";
let original = padRightTo32("Hello");
let cipher = new Rijndael(key, "ecb");
let ciphertext = cipher.encrypt(original, 128);
console.log(ciphertext.toString("hex"));
I get this result e97282fb5838a9c78e6df1f1b4aad108aa010418ec573d74b9c991f4e897e752 but not the encrypted text that Iget from in java. Trying the 256 block size doesn't help either.
what I'm missing that is resulting in a different output?
Concerning your key you have to convert your hex-string into binary data using a buffer (see e.g. Encrypt binary data with aes-ecb on node.js).
Moreover, you have to use the method crypto.createCipheriv to instantiate the cipher (see e.g. https://nodejs.org/api/crypto.html#crypto_crypto_createcipheriv_algorithm_key_iv_options).
The currently used (deprecated) method crypto.creataCipher expects a password and generates the key from the password (see e.g. https://nodejs.org/api/crypto.html#crypto_crypto_createcipher_algorithm_password_options).
The following code
crypto = require('crypto');
function encrypt(data,key) {
var cipher = crypto.createCipheriv('aes-128-ecb', key,''); //create aes-128 cipher
var encrypted = cipher.update(data,'utf8', 'hex'); //output as hex
return encrypted;
}
function padRightTo32(str) { // ensure block size of 32
len=str.length;
for(i=len; i%32>0; i++) {
str=str +" ";
}
return str;
}
// call to encryption function
var hexKey = new Buffer('3b6ce332ca3b6519eac769710f41ca5c', 'hex'); // 16 Byte-key
encStr=encrypt(padRightTo32("Hello"),hexKey);
console.log(encStr);
has the output
cc0ac95b5ffd4758dbfa40f909c285f0f86a8f19ed1a12c1bfc098348a2ac683
which is equal to the output of the Java code.
In Java the length of the key defines the used AES-variant, e.g. if you choose a 16-Byte key AES-128 is used, if a 32-Byte key is chosen, AES-256 is used.
In the nodejs-code you have to explicitly specifiy the AES-variant, i.e. aes-128-ecb for a 16-Byte key, and aes-256-ecb for a 32-Byte key etc.
As already mentioned in the comments ECB in't a secure mode (see e.g. https://crypto.stackexchange.com/questions/20941/why-shouldnt-i-use-ecb-encryption).
I don't know if there is really a difference between Rijndael/ECB/NoPadding and AES/ECB/NoPadding concerning the cipher-instantiation in Java. In my testcases at least the results are identical. Thus, for the nodejs-code the selection of aes-128-ecb (for 16-Byte key) or aes-256-ecb (for 32-Byte keys) should work.

Get text from javascript alert box in vb.net with user32.dll

Hy guys!
Please help me out;
I'm trying to get the text from an javascript alert box with user32.dll API but i can't figure out the lpszClass name.
Please someone help me out and sorry if it's a dumb question.
<DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function FindWindowEx(hwndParent As IntPtr, hwndChildAfter As IntPtr, lpszClass As String, lpszWindow As String) As IntPtr
End Function
<DllImport("user32.dll", EntryPoint:="FindWindow", SetLastError:=True)> _
Private Shared Function FindWindow(lpClassName As String, lpWindowName As String) As IntPtr
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Private Shared Function SendMessage(hWnd As IntPtr, Msg As UInt32, wParam As IntPtr, lParam As IntPtr) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function GetWindowText(ByVal hwnd As IntPtr, ByVal lpString As System.Text.StringBuilder, ByVal cch As Integer) As Integer
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function GetWindowTextLength(ByVal hwnd As IntPtr) As Integer
End Function
Private Function Form1_Deactivate(sender As Object, e As EventArgs) Handles Me.Deactivate As String
Dim hwnd As IntPtr = FindWindow("#32770", "Mensagem da página da web")
'hwnd = FindWindowEx(hwnd, IntPtr.Zero, "<NEED TO KNOW WHAT TO PUT HERE", Nothing)
Dim length As Integer = GetWindowTextLength(hwnd)
Dim sb As New System.Text.StringBuilder("", length + 1)
GetWindowText(hwnd, sb, sb.Capacity)
return sb.ToString()
End Function
Fellow Windows API noob here, but here's how I did something similar:
VisualStudio comes with a tool called Spy++ (it's under the Tools menu) that lists every "window" on the system along with the relevant information. The information you are looking for is shown right after the window title:
In my case, I needed to find multiple children with the same class, so I ended up using the EnumChildWindows function instead of FindWindowEx. Here's my code in Java (using JNA):
User32 u32 = User32.INSTANCE;
WinDef.HWND window = u32.FindWindow("#32770", "Control Center Login");
List<WinDef.HWND> windows = new ArrayList<>();
u32.EnumChildWindows(window, (child, data) -> {
char[] name = new char[256];
u32.GetClassName(child, name, 256);
String nameStr = new String(name).trim();
if(nameStr.equals("Edit")) {
windows.add(child);
}
return true;
}, null);
I hope you have not been waiting for this answer for the past 2 years, but if someone else finds this question, here's a way to do it :)

while assigning value to asp hidden field, escape character gets cleared

I am following one strange issue. Following is the detailed description
My object of JSON String
public class ChartSearchCriteria
{
public ChartSearchCriteria()
{
}
public DateTime StartDate
{
get;
set;
}
public DateTime EndDate
{
get;
set;
}
public Int32 ClassType
{
get;
set;
}
public Int32 InstructorID
{
get;
set;
}
}
I am converting this object to JSON string and assigning to one hidden field
ChartSearchCriteria objChartSearchCriteria = new ChartSearchCriteria()
{
StartDate = startDate,
EndDate = endDate,
ClassType = Convert.ToInt32(ddlClassType.SelectedValue)
};
string jsonSearchCriteria = new JavaScriptSerializer().Serialize(objChartSearchCriteria);
// Here in jsonSearchCriteria i am getting following string
// "{\"StartDate\":\"\\/Date(1436466600000)\\/\",\"EndDate\":\"\\/Date(1439145000000)\\/\",\"ClassType\":0,\"InstructorID\":0}"
hdnSearchData.Value = jsonSearchCriteria;
I want to pass this json string to another page with query string. I have used following javascript to get url
alert(document.getElementById("hdnSearchData").value);
// Here i am getting following JSON string from hidden field
// {"StartDate":"\/Date(1436466600000)\/","EndDate":"\/Date(1439145000000)\/","ClassType":0,"InstructorID":0}
var searchData = JSON.parse(document.getElementById("hdnSearchData").value);
var redirectUrl = _spPageContextInfo.webAbsoluteUrl + "/_layouts/15/DetailedChart.aspx?searchdata=" + encodeURIComponen(JSON.stringify(searchData));
Now I have used following code to Deserialize that json string to object into another page where I have passed that json string as query string
string jsonString = Convert.ToString(Page.Request.QueryString["searchdata"]);
jsonString = HttpUtility.UrlDecode(jsonString);
// Here I am getting following json string
// {"StartDate":"\/Date(1436466600000)\/","EndDate":"\/Date(1439145000000)\/","ClassType":0,"InstructorID":0}
JavaScriptSerializer oJS = new JavaScriptSerializer();
ChartSearchCriteria oRootObject = new ChartSearchCriteria();
oRootObject = oJS.Deserialize<ChartSearchCriteria>(jsonString);
So here i am getting exception like:
"Date(234234000)" cannot be converted to date time when Deserializing json string to object
The only thing which I get is that while assigning to json string to hidden field, It is losing escape character from json.
JSON String created from server side :
{\"StartDate\":\"\/Date(1436466600000)\/\",\"EndDate\":\"\/Date(1439145000000)\/\",\"ClassType\":0,\"InstructorID\":0}"
JSON string gotten from client side using javascript:
{"StartDate":"/Date(1436466600000)/","EndDate":"/Date(1439145000000)/","ClassType":0,"InstructorID":0}
So you can see above both different string which shows while assigning json string to hidden field , it is removing escape characters and that's why I cannot convert it back to object into another page.
I am sure 100% that it is issue related to escape character because i have checked deserialize method with following string and it is working fine
{\"StartDate\":\"\/Date(1436466600000)\/\",\"EndDate\":\"\/Date(1439145000000)\/\",\"ClassType\":0,\"InstructorID\":0}"
So how can I resolve that issue? My final goal is to pass json string to another page and deserializing into same object.
Any help will be highly appreciated and let me know anyone want some more information on it.
I have resolved issue by using following code.
string jsonString = Convert.ToString(Page.Request.QueryString["searchdata"]);
jsonString = HttpUtility.UrlDecode(jsonString);
// Here I am getting following json string
// {"StartDate":"\/Date(1436466600000)\/","EndDate":"\/Date(1439145000000)\/","ClassType":0,"InstructorID":0}
// By using following line I have corrected json string and now it is being deserialized to object.
jsonString = jsonString.Replace("/", "\\/");
JavaScriptSerializer oJS = new JavaScriptSerializer();
ChartSearchCriteria oRootObject = new ChartSearchCriteria();
oRootObject = oJS.Deserialize<ChartSearchCriteria>(jsonString);

VB 2013: Auto login from my.settings issue

I am using the latest version of Awesomium for the WebControl for my application. When my application arrives at "accounts.google.com/ServiceLogin" it is supposed to execute some Javascript to have it automatically log in. In my.settings.java I have:
"document.getElementById('Email').value=""1"";document.getElementById('Passwd').value=""2"";document.getElementById('signIn').click()"
Value "1" being the email, and "2" being the password. So when the document is ready I have this:
Private Sub WebBrowser1_DocumentReady(sender As Object, e As Awesomium.Core.UrlEventArgs) Handles WebBrowser1.DocumentReady
If WebBrowser1.Source.ToString.Contains("accounts.google.com/ServiceLogin") = True Then
WebBrowser1.ExecuteJavascript(My.Settings.java.ToString)
Else
End If
I don't know why this is not working. When I paste the code directly in like this:
WebBrowser1.ExecuteJavascript("document.getElementById('Email').value=""1"";document.getElementById('Passwd').value=""2"";document.getElementById('signIn').click()")
The code works perfectly and it logs in. The reason I have it in my.settings is because I originally have it in a textbox, then I ask the user for their email and password, and then replace "1" with the email, and "2" with the password, then save the edited textbox text in my.settings.java. Then I have it look for the Javascript there instead of hard coding it into the application, and not being able to customize it for each user. Is any of my code wrong, or is there another way of doing this with Awesomium. Also, I am using the Awesomium WebControl1, I just changed it to WebBrowser1 because that is what I am used to typing. Sorry if this question is simple, as I am a student developer, with very limited knowledge in Javascript.
I never user my.settings when it comes to sensitive data like passwords (even emails). What I always do, I encrypt them in XML file using a simple yet dynamic encryption like this :
Public Function Encrypt(ByVal plainText As String) As String
Dim passPhrase As String = **My.Computer.Name.ToString**
Dim saltValue As String = **My.Computer.Info.OSFullName.ToString**
Dim hashAlgorithm As String = "SHA1"
Dim passwordIterations As Integer = 2
Dim initVector As String = "#1B2c3D4e5F6g7H8"
Dim keySize As Integer = 256
Dim initVectorBytes As Byte() = Encoding.ASCII.GetBytes(initVector)
Dim saltValueBytes As Byte() = Encoding.ASCII.GetBytes(saltValue)
Dim plainTextBytes As Byte() = Encoding.UTF8.GetBytes(plainText)
Dim password As New PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations)
Dim keyBytes As Byte() = password.GetBytes(keySize \ 8)
Dim symmetricKey As New RijndaelManaged()
symmetricKey.Mode = CipherMode.CBC
Dim encryptor As ICryptoTransform = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes)
Dim memoryStream As New IO.MemoryStream()
Dim cryptoStream As New CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length)
cryptoStream.FlushFinalBlock()
Dim cipherTextBytes As Byte() = memoryStream.ToArray()
memoryStream.Close()
cryptoStream.Close()
Dim cipherText As String = Convert.ToBase64String(cipherTextBytes)
Return cipherText
End Function
Public Function Decrypt(ByVal cipherText As String) As String
Dim passPhrase As String = **My.Computer.Name.ToString**
Dim saltValue As String = **My.Computer.Info.OSFullName.ToString**
Dim hashAlgorithm As String = "SHA1"
Dim passwordIterations As Integer = 2
Dim initVector As String = "#1B2c3D4e5F6g7H8"
Dim keySize As Integer = 256
Dim initVectorBytes As Byte() = Encoding.ASCII.GetBytes(initVector)
Dim saltValueBytes As Byte() = Encoding.ASCII.GetBytes(saltValue)
Dim cipherTextBytes As Byte() = Convert.FromBase64String(cipherText)
Dim password As New PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations)
Dim keyBytes As Byte() = password.GetBytes(keySize \ 8)
Dim symmetricKey As New RijndaelManaged()
symmetricKey.Mode = CipherMode.CBC
Dim decryptor As ICryptoTransform = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes)
Dim memoryStream As New IO.MemoryStream(cipherTextBytes)
Dim cryptoStream As New CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)
Dim plainTextBytes As Byte() = New Byte(cipherTextBytes.Length - 1) {}
Dim decryptedByteCount As Integer = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length)
memoryStream.Close()
cryptoStream.Close()
Dim plainText As String = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount)
Return plainText
End Function
And it's still not that safe. The best way is to let the user put the password.
As for your answer , if I understand you question, you need to create profiles, and store them in files/registry. (I recommend files or database). So that when "John" uses your program, he will select the "John" profile ... and so on.

Categories

Resources