I have a tool which creates a signature. I am looking for equivalent code in dot net core 2.1.
Java Code: sign(currentdate,'some text','SHA1WithRSA')
public String sign(String date, String subjectId, String algorithm){
Signature rsa = Signature.getInstance(algorithm);
rsa.initSign(this.getPrivate());
rsa.update(subjectId.getBytes());
rsa.update(date.getBytes());
String signature = new String(Base64.getEncoder().encode(rsa.sign()));
return signature;
}
public PrivateKey getPrivate() {
String privateKeyPEM = "<This is the private key string";
byte[] encoded = Base64.getDecoder().decode(privateKeyPEM);
KeyFactory kf = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(encoded);
return kf.generatePrivate(spec);
}
Suggest a way to generate dot net core 2.1 equivalent code for the above with or without 3rd party tool.
This is work for me using Portable.BouncyCastle library.
private string GetSign(string data)
{
using (var rsa = new RSACryptoServiceProvider())
{
var privateKey = new StringBuilder();
privateKey.AppendLine("-----BEGIN RSA PRIVATE KEY-----");
privateKey.AppendLine("private key as string");
privateKey.AppendLine("-----END RSA PRIVATE KEY-----");
var pem = new PemReader(new StringReader(privateKey.ToString()));
var keyPair = (AsymmetricCipherKeyPair)pem.ReadObject();
var privateKeyParameters = (RsaPrivateCrtKeyParameters)keyPair.Private;
var rsaParameters = DotNetUtilities.ToRSAParameters(privateKeyParameters);
rsa.ImportParameters(rsaParameters);
var sign = rsa.SignData(Encoding.UTF8.GetBytes(data), new HashAlgorithmName("SHA1") /*pass your algorithm*/,
RSASignaturePadding.Pkcs1);
return Convert.ToBase64String(sign);
}
}
Related
I am trying to implement AEPS API but unable to encrypt aadhar number in php. In developer guide they provided method to encrypt using JAVA and i am using php.
Given JAVA code is as follows.
public static String calculateRSA( String salt ) throws InvalidKeyException, Exception {
Cipher encryptCipher = Cipher.getInstance("RSA");
encryptCipher.init(Cipher.ENCRYPT_MODE, getPublicKey());
byte[] secretMessageBytes = salt.getBytes("UTF-8");
byte[] encryptedMessageBytes = encryptCipher.doFinal(secretMessageBytes);
String encodedMessage = Base64.encodeBase64String(encryptedMessageBytes);
return encodedMessage;
}
public static PublicKey getPublicKey() throws Exception {
String rawPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCaFyrzeDhMaFLx+LZUNOOO14Pj9aPfr+1WOanDgDHxo9NekENYcWUftM9Y17ul2pXr3bqw0GCh4uxNoTQ5cTH4buI42LI8ibMaf7Kppq9MzdzI9/7pOffgdSn+P8J64CJAk3VrVswVgfy8lABt7fL8R6XReI9x8ewwKHhCRTwBgQIDAQAB";
byte[] keyBytes = Base64.decodeBase64(rawPublicKey);
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);// generatePrivate(spec);
}
I tried
$publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCaFyrzeDhMaFLx+LZUNOOO14Pj9aPfr+1WOanDgDHxo9NekENYcWUftM9Y17ul2pXr3bqw0GCh4uxNoTQ5cTH4buI42LI8ibMaf7Kppq9MzdzI9/7pOffgdSn+P8J64CJAk3VrVswVgfy8lABt7fL8R6XReI9x8ewwKHhCRTwBgQIDAQAB';
include('Crypt/RSA.php');
$rsa = new Crypt_RSA();
$rsa->loadKey($publicKey); // public key
$plaintext = '828409353766';
//$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_OAEP);
$encrypted = $rsa->encrypt($plaintext);
$encrypted = base64_encode($encrypted);
I have to write PHP program to do the same function with the java sign function as follow
public static String sign(byte[] data, String privateKey) throws Exception {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(data);
byte[] hashData = messageDigest.digest();
StringBuffer hexString = new StringBuffer();
byte[] keyBytes = Base64Utils.decode(privateKey.getBytes());
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Signature signature = Signature.getInstance("NONEWithRSA");
signature.initSign(privateK);
signature.update(hashData);
byte[] sign = signature.sign();
return Base64.getEncoder().encodeToString(sign);
}
I have done some research on google and try to write the PHP code as follow
public function sign($data, $privateKeyString){
$privateKey = openssl_pkey_get_private($privateKeyString);
$hashData = hash("sha256",$data);
openssl_sign($hashData, $signature, $privateKey);
openssl_free_key($privateKey);
return base64_encode($signature);
}
I try to pass the same key with the data let's say "Hello" to both function and testing
the hash data are map but the outcome signature are different
Is there anyone can spot what cause the return base64 signature are different between the java and php?
public function sign($data, $privateKeyString){
$privateKey = openssl_pkey_get_private($privateKeyString);
$hashData = openssl_digest("sha256",$data);
openssl_private_encrypt($hashData, $signature, $privateKey);
openssl_free_key($privateKey);
return base64_encode($signature);
}
Finally fixing the problem by using openssl_digest "sha256" instead of passing sha256 hash value into the for private key encrytion, due to the hashing need to be convert into the hex string instead of the original value.
I have following java method where i need to convert into nodejs, the problems was the output from nodejs seems rather odd.
Here is my java code
private static final String SIGN_ALGORITHMS = "MD5WithRSA";
public static String sign(String content, String privateKey, String input_charset) {
try {
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decode(privateKey));
KeyFactory keyf = KeyFactory.getInstance("RSA");
PrivateKey priKey = keyf.generatePrivate(priPKCS8);
java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
signature.initSign(priKey);
signature.update(content.getBytes(input_charset));
byte[] signed = signature.sign();
return Base64.encode(signed);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
where:
content is just regular string to encrypt e.g: lorem ipsum,
privateKey is string representation of private key, and
input_charset is UTF-8
How do i get the value of Base64.encode(signed) in nodejs?
Just use NodeJS in built Crypto functions:
https://nodejs.org/dist/latest-v10.x/docs/api/crypto.html#crypto_crypto
I have a String stored in a variable:
-----BEGIN RSA PUBLIC KEY-----
MIGHAoGBANAahj75ZIz9nXqW2H83nGcUao4wNyYZ9Z1kiNTUYQl7ob/RBmDzs5rY
mUahXAg0qyS7+a55eU/csShf5ATGzAXv+DDPcz8HrSTcHMEFpuyYooX6PrIZ07Ma
XtsJ2J4mhlySI5uOZVRDoaFY53MPQx5gud2quDz759IN/0gnDEEVAgED
-----END RSA PUBLIC KEY-----
I generate public key as:
public static PublicKey getFromString(String keystr) throws Exception
{
//String S1= asciiToHex(keystr);
byte[] keyBytes = new sun.misc.BASE64Decoder().decodeBuffer(keystr);
ASN1InputStream in = new ASN1InputStream(keyBytes);
DERObject obj = in.readObject();
RSAPublicKeyStructure pStruct = RSAPublicKeyStructure.getInstance(obj);
RSAPublicKeySpec spec = new RSAPublicKeySpec(pStrcut.getModulus(), pStruct.getPublicExponent());
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
How to generate the PrivateKey using bouncy castle in android
{Edit}
Without using bouncy castle i am generating private key like this:
public static PrivateKey getKey(String mKey){
try{
// Read in the key into a String
StringBuilder pkcs8Lines = new StringBuilder();
BufferedReader rdr = new BufferedReader(new StringReader(mKey));
String line;
while ((line = rdr.readLine()) != null) {
pkcs8Lines.append(line);
}
// Remove the "BEGIN" and "END" lines, as well as any whitespace
String pkcs8Pem = pkcs8Lines.toString();
pkcs8Pem = pkcs8Pem.replace("-----BEGIN RSA PRIVATE KEY-----", "");
pkcs8Pem = pkcs8Pem.replace("-----END RSA PRIVATE KEY-----", "");
pkcs8Pem = pkcs8Pem.replaceAll("\\s+","");
// Base64 decode the result
byte [] pkcs8EncodedBytes = Base64.decode(pkcs8Pem, Base64.DEFAULT);
// extract the private key
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8EncodedBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privKey = kf.generatePrivate(keySpec);
System.out.println(privKey);
return privKey;
}catch (Exception ex){
ex.printStackTrace();
}
return null;
}
I want to achieve the same using Bouncy Castle
I'm a little confused on why you insist on using bouncycastle, but if you really want to use bouncycastle then the CMS/PKIX library has a nice helper class called PEMParser that will shorten the code needed, e.g:
public static PrivateKey getPemPrivateKey(String mKey) throws Exception {
PEMParser pemParser = new PEMParser(new StringReader(mKey));
final PEMKeyPair pemKeyPair = (PEMKeyPair) pemParser.readObject();
final byte[] encoded = pemKeyPair.getPrivateKeyInfo().getEncoded();
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(new PKCS8EncodedKeySpec(encoded));
}
I have signature created in Java by following code
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
signature = (Signature) rsaSha256.getCipher();
signature.initSign(privateKey);
signature.update(binaryData);
signatureBytes = signature.sign();
By verifying signature in C#, im always getting false. Following code use BouncyCastle library
ISigner signer = SignerUtilities.GetSigner("SHA256withRSA");
using (TextReader sr = new StringReader(publicKey))
{
PemReader pr = new PemReader(sr);
RsaKeyParameters keys = (RsaKeyParameters)pr.ReadObject();
signer.Init(false, keys);
signer.BlockUpdate(value, 0, value.Length);
bool isValid = signer.VerifySignature(signature);
return isValid;
}
Following code return false too
private static bool VerifyWithPublicKey(byte[] data, byte[] sig, string publicKey)
{
RSACryptoServiceProvider rsa;
using (var keyreader = new StringReader(publicKey))
{
var pemReader = new PemReader(keyreader);
var y = (RsaKeyParameters)pemReader.ReadObject();
RSAParameters p1 = DotNetUtilities.ToRSAParameters(y);
rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(p1);
}
byte[] hash;
using (var sha256 = SHA256.Create())
{
hash = sha256.ComputeHash(data);
}
RSAPKCS1SignatureDeformatter RSADeformatter = new RSAPKCS1SignatureDeformatter(rsa);
RSADeformatter.SetHashAlgorithm("SHA256");
//Verify the hash and display the results to the console.
if (RSADeformatter.VerifySignature(hash, sig))
{
Console.WriteLine("The signature was verified.");
}
else
{
Console.WriteLine("The signature was NOT verified.");
}
// This always returns false
return rsa.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA256"), sig);
}
Im out of ideas. Anyone done something similar? If so, can you share your code please
This works for me, I see a difference where you use .GetSigner("SHA256withRSA") but I use "SHA-256withRSA"
public static bool VerifySignature(byte[] hashBytes, byte[] signatureBytes)
{
PemReader pemReader = new PemReader(new StreamReader("PublicKey.pem"));
RsaKeyParameters parameters = (RsaKeyParameters)pemReader.ReadObject();
RsaDigestSigner signer = (RsaDigestSigner)SignerUtilities.GetSigner("SHA-256withRSA");
signer.Init(false, parameters);
signer.BlockUpdate(hashBytes, 0, hashBytes.Length);
bool isValid = signer.VerifySignature(signatureBytes);
return isValid;
}