1) How to get ECDSAPublicKey, ECDSAPrivateKey from DER encoded pem string
2) How to Marshal and Unmarshal ECDSAPublicKey,ECDSAPrivateKey using PKCS8 or PKCS1
3) I got ECPublicKey from ECPrivateKey , How to get ECDSAPublicKey directly from pem string instead of getting it from private key
String pemPkString = '''-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg6ZuZLImVj3CA2IE3
21G5mOK65KL71ost37cf2wrc7WChRANCAATMME1IAtwwoD53/IBUOY0H+ua6LKHj
yMhGPi/8dPz9h5FMyXHJQmXI3yEmW/tnyIRu6Z8PmAsVvKX8CnSC9fY6
-----END PRIVATE KEY-----''';
String pemPubString = '''-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEzDBNSALcMKA+d/yAVDmNB/rmuiyh
48jIRj4v/HT8/YeRTMlxyUJlyN8hJlv7Z8iEbumfD5gLFbyl/Ap0gvX2Og==
-----END PUBLIC KEY-----''';
String msgToSign = "Hai this is test";
var domainParams = new ECDomainParameters("secp256k1");
void main() {
privateKey = parsePrivateKey(pemPkString);
publicKey = publicKeyFromPrivateKey(privateKey);
var privParams = new PrivateKeyParameter(privateKey);
var signParams =
() => new ParametersWithRandom(privParams, new NullSecureRandom());
generateSignature(new ECDSASigner(), signParams, msgToSign);
var verifyParams = () => new PublicKeyParameter(publicKey);
verifySign(new ECDSASigner(), verifyParams, msgToSign, signature);
}
ECPrivateKey parsePrivateKey(String pemPkString) {
List<int> encodedPkData = PemCodec(PemLabel.privateKey).decode(pemPkString);
BigInt d = decodeBigInt(encodedPkData);
return new ECPrivateKey(d, domainParams);
}
//Get ECPublicKey from ECPrivateKey
ECPublicKey publicKeyFromPrivateKey(ECPrivateKey privateKey) {
ECPoint Q = privateKey.parameters.G * privateKey.d;
return new ECPublicKey(Q, privateKey.parameters);
}
void generateSignature(
Signer signer, CipherParameters params(), String message) {
signer.reset();
signer.init(true, params());
signature =
signer.generateSignature(sha256.convert(utf8.encode(message)).bytes);
print("Signature ");
print(encodeSignatureToPem(signature));
}
void verifySign(Signer signer, CipherParameters params(), String message,
Signature signature) {
signer.reset();
signer.init(false, params());
var ok = signer.verifySignature(
sha256.convert(utf8.encode(message)).bytes, signature);
print("Verified $ok");
}
String encodeSignatureToPem(ECSignature signature) {
var topLevel = new ASN1Sequence();
topLevel.add(ASN1Integer(signature.r));
topLevel.add(ASN1Integer(signature.s));
var dataBase64 = base64Encode(topLevel.encodedBytes);
return dataBase64;
}
Related
I have a setup where I need to encrypt blob of data in one app and decrypt it in different app.
I built a sample app that creates a named CngKey object. Then create a RSACng using CngKey object. Then use RSACng object to do encryption/decryption. What I found is that the key changes across restarts of the application even though it is loaded using the name it was created with. I am lost trying to understand the relation between CngKey and RSACng objects.
Below is snippet of code that describes what I am trying to do:
using System;
using System.IO;
using System.Security.Cryptography;
namespace TPMCrypto
{
class Program
{
static byte[] data = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
static byte[] privateKey;
private static byte[] encrypted;
private static byte[] decrypted;
static void Main(string[] args)
{
const string MyKey = "MyRSAKey";
CngKey cngKey = null;
string cmd = args.Length > 0 ? args[0] : "";
try
{
CngKeyCreationParameters cng = new CngKeyCreationParameters
{
KeyUsage = CngKeyUsages.AllUsages,
KeyCreationOptions = CngKeyCreationOptions.MachineKey,
Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider
};
if (!CngKey.Exists(MyKey, CngProvider.MicrosoftSoftwareKeyStorageProvider, CngKeyOpenOptions.MachineKey))
{
Console.WriteLine("Creating rsaKey");
cngKey = CngKey.Create(CngAlgorithm.Rsa, MyKey, cng);
}
else
{
Console.WriteLine("Opening rsaKey");
cngKey = CngKey.Open(MyKey, CngProvider.MicrosoftSoftwareKeyStorageProvider, CngKeyOpenOptions.MachineKey);
}
RSACng rsaKey = new RSACng(cngKey)
{
KeySize = 2048
};
privateKey = rsaKey.Key.Export(CngKeyBlobFormat.GenericPrivateBlob);
string prvResult = ByteArrayToHexString(privateKey, 0, privateKey.Length);
Console.WriteLine("\nPrivate key - length = " + privateKey.Length + "\n" + prvResult + "\n");
const string FILE_PATH = #"\temp\tpmtests\encryptedblob.dat";
// Encrypt / decrypt
if (cmd == "readfromfile")
{
Directory.CreateDirectory(Path.GetDirectoryName(FILE_PATH));
encrypted = File.ReadAllBytes(FILE_PATH);
}
else if (cmd == "deletekey")
{
cngKey.Delete();
return;
}
else
{
encrypted = Encrypt(rsaKey, data);
Console.WriteLine("The encrypted blob: ");
Console.WriteLine(ByteArrayToHexString(encrypted, 0, encrypted.Length));
File.WriteAllBytes(FILE_PATH, encrypted);
}
decrypted = Decrypt(rsaKey, encrypted);
bool result = ByteArrayCompare(data, decrypted);
if (result)
Console.WriteLine("Encrypt / decrypt works");
else
Console.WriteLine("Encrypt / decrypt fails");
}
catch (Exception e)
{
Console.WriteLine("Exception " + e.Message);
}
finally
{
if (cngKey != null)
cngKey.Dispose();
}
Console.ReadLine();
}
static bool ByteArrayCompare(byte[] a1, byte[] a2)
{
if (a1.Length != a2.Length)
return false;
for (int i = 0; i < a1.Length; i++)
if (a1[i] != a2[i])
return false;
return true;
}
public static string ByteArrayToHexString(byte[] bytes, int start, int length)
{
string delimitedStringValue = BitConverter.ToString(bytes, start, length);
return delimitedStringValue.Replace("-", "");
}
public static byte[] Sign512(byte[] data, byte[] privateKey)
{
CngKey key = CngKey.Import(privateKey, CngKeyBlobFormat.GenericPrivateBlob);
RSACng crypto = new RSACng(key);
return crypto.SignData(data, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
}
public static bool VerifySignature512(byte[] data, byte[] signature, byte[] publicKey)
{
CngKey key = CngKey.Import(publicKey, CngKeyBlobFormat.GenericPublicBlob);
RSACng crypto = new RSACng(key);
return crypto.VerifyData(data, signature, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
}
public static byte[] Encrypt(byte[] publicKey, byte[] data)
{
CngKey key = CngKey.Import(publicKey, CngKeyBlobFormat.GenericPublicBlob);
RSACng crypto = new RSACng(key);
var result = Encrypt(crypto, data);
return result;
}
public static byte[] Encrypt(RSACng crypto, byte[] data)
{
if (null == crypto)
return null;
var result = crypto.Encrypt(data, RSAEncryptionPadding.OaepSHA512);
return result;
}
public static byte[] Decrypt(byte[] privateKey, byte[] data)
{
CngKey key = CngKey.Import(privateKey, CngKeyBlobFormat.GenericPrivateBlob);
RSACng crypto = new RSACng(key);
var result = Decrypt(crypto, data);
return result;
}
public static byte[] Decrypt(RSACng aKey, byte[] data)
{
if (null == aKey)
return null;
var result = aKey.Decrypt(data, RSAEncryptionPadding.OaepSHA512);
return result;
}
}
}
I am aware of dpapi and how to do this using it. I don't want to use it for this, please don't point me in that direction. I am using CNG flavor of crypto to force C# use NCryptXYZ crypto calls and the desire is to secure the keys in TPM.
Ah, looking at your code again, you've made a goof.
RSACng rsaKey = new RSACng(cngKey)
{
KeySize = 2048
};
Setting the KeySize property on an RSACng does one of two things:
If get_KeySize == value, ignore the input, do nothing.
Else, detach from the current key and the next time the key is used, generate a new key of get_KeySize at the time.
So you're opening an existing key, then discarding it, and generating a new ephemeral key. (Which you could see by checking rsaKey.Key.Name, it won't match your input).
Presumably you did this as a way to create the key with the right size in the first place, but you're too late. The correct way is
CngKeyCreationParameters cng = new CngKeyCreationParameters
{
KeyUsage = CngKeyUsages.AllUsages,
KeyCreationOptions = CngKeyCreationOptions.MachineKey,
Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider,
Parameters =
{
new CngProperty("Length", BitConverter.GetBytes(2048), CngPropertyOptions.Persist),
},
};
I am trying to implement JWE token in Swift using JOSESwift (modified to support AES-GCM 256) and CryptoSwift(need to support iOS 11+). I am able to encrypt and decrypt using public/private key pair. But when the same JWE token passed on to Java (server-side program) it's not able to decrypt. Vice e versa is also not working. Need help, can share my github project
https://github.com/sreekanthps/VAMDemoJava.git - Java project https://github.com/sreekanthps/VMADemo.git - iOS project https://github.com/sreekanthps/JOSESwift-AES256GCM.git - modified JOSESwift project
Nimbus
Exception in thread "main" com.nimbusds.jose.JOSEException: AES/GCM/NoPadding decryption failed: Tag mismatch!
at com.nimbusds.jose.crypto.impl.AESGCM.decrypt(AESGCM.java:301)
at com.nimbusds.jose.crypto.impl.ContentCryptoProvider.decrypt(ContentCryptoProvider.java:279)
at com.nimbusds.jose.crypto.RSADecrypter.decrypt(RSADecrypter.java:285)
at com.nimbusds.jose.JWEObject.decrypt(JWEObject.java:415)
at me.txedo.security.Main.numbusJWe(Main.java:127)
at me.txedo.security.Main.main(Main.java:52)
Jose4j
Exception in thread "main" org.jose4j.lang.JoseException: javax.crypto.AEADBadTagException: Tag mismatch!
at org.jose4j.jwe.SimpleAeadCipher.decrypt(SimpleAeadCipher.java:114)
at org.jose4j.jwe.SimpleAeadCipher.decrypt(SimpleAeadCipher.java:101)
at org.jose4j.jwe.AesGcmContentEncryptionAlgorithm.decrypt(AesGcmContentEncryptionAlgorithm.java:79)
at org.jose4j.jwe.JsonWebEncryption.decrypt(JsonWebEncryption.java:249)
at org.jose4j.jwe.JsonWebEncryption.getPlaintextBytes(JsonWebEncryption.java:85)
at org.jose4j.jwe.JsonWebEncryption.getPlaintextString(JsonWebEncryption.java:78)
at org.jose4j.jwe.JsonWebEncryption.getPayload(JsonWebEncryption.java:93)
at me.txedo.security.Main.jose4JDeryption(Main.java:166)
at me.txedo.security.Main.main(Main.java:55)
Swift code
keyData = try! randomData(ofLength: 32)
ivData = try! randomData(ofLength: 16)
let message = "Summer ⛱, Sun ☀️, Cactus 🌵".data(using: .utf8)!
let header = JWEHeader(keyManagementAlgorithm: .RSAOAEP256, contentEncryptionAlgorithm: .AES256GCM)
let payload = Payload(message)
let publickey = RSAKeyGenerator.shared.getPublicKey()
let privateKey = RSAKeyGenerator.shared.getPrivateKey()
let encrypter = Encrypter(keyManagementAlgorithm: .RSAOAEP256, contentEncryptionAlgorithm: .AES256GCM, encryptionKey: publickey!)!
if let jwe = try? JWE(header: header, payload: payload, encrypter: encrypter) {
jwtString = jwe.compactSerializedString
print("jwtString : \(jwtString!)")
}
do {
let jwe = try JWE(compactSerialization: jwtString!)
let decrypter = Decrypter(keyManagementAlgorithm: .RSAOAEP256, contentEncryptionAlgorithm: .AES256GCM, decryptionKey: privateKey!)!
let payload = try jwe.decrypt(using: decrypter)
let message = String(data: payload.data(), encoding: .utf8)!
print(message) // Summer ⛱, Sun ☀️, Cactus 🌵
}catch {
print("Decryption error :\(error.localizedDescription)")
}
Java Code
protected final static Logger LOGGER = Logger.getLogger(Main.class);
public final static String RESOURCES_DIR = "/Users/swesree/Desktop/KH802/CERTS/";
public static void main(String[] args) throws FileNotFoundException,
IOException, NoSuchAlgorithmException, NoSuchProviderException, ParseException, JOSEException, JoseException {
Security.addProvider(new BouncyCastleProvider());
LOGGER.info("BouncyCastle provider added.");
KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
try {
PrivateKey priv = generatePrivateKey(factory, RESOURCES_DIR + "vmaprivate.pem");
LOGGER.info(String.format("Instantiated private key: %s", priv));
PublicKey pub = generatePublicKey(factory, RESOURCES_DIR + "vmapublic.pem");
LOGGER.info(String.format("Instantiated public key: %s", pub));
//numbusJWe(pub,priv);
String jweString = jose4JEcnryption(pub);
jose4JDeryption(priv,jweString);
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
}
private static PrivateKey generatePrivateKey(KeyFactory factory, String filename)
throws InvalidKeySpecException, FileNotFoundException, IOException {
PemFile pemFile = new PemFile(filename);
byte[] content = pemFile.getPemObject().getContent();
PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
return factory.generatePrivate(privKeySpec);
}
private static PublicKey generatePublicKey(KeyFactory factory, String filename)
throws InvalidKeySpecException, FileNotFoundException, IOException {
PemFile pemFile = new PemFile(filename);
byte[] content = pemFile.getPemObject().getContent();
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content);
return factory.generatePublic(pubKeySpec);
}
private static void numbusJWe(PublicKey publicKey, PrivateKey privKey) throws ParseException, JOSEException {
Date now = new Date();
JWTClaimsSet jwtClaims = new JWTClaimsSet.Builder()
.issuer("https://openid.net")
.subject("alice")
.audience(Arrays.asList("https://app-one.com", "https://app-two.com"))
.expirationTime(new Date(now.getTime() + 1000*60*10)) // expires in 10 minutes
.notBeforeTime(now)
.issueTime(now)
.jwtID(UUID.randomUUID().toString())
.build();
System.out.println(jwtClaims.toJSONObject());
// Request JWT encrypted with RSA-OAEP-256 and 128-bit AES/GCM
JWEHeader header = new JWEHeader(JWEAlgorithm.RSA_OAEP_256, EncryptionMethod.A256GCM);
// Create the encrypted JWT object
EncryptedJWT jwt = new EncryptedJWT(header, jwtClaims);
// Create an encrypter with the specified public RSA key
RSAEncrypter encrypter = new RSAEncrypter((RSAPublicKey) publicKey);
// Do the actual encryption
jwt.encrypt(encrypter);
// Serialise to JWT compact form
String jwtString = jwt.serialize();
System.out.println("jwtString : "+jwtString);
//
//
// Parse back
//String jwtStringNew = "eyJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.hJ905rCCsW0u07cCleTh_eYKAyDP7ZHNnRA50qDWXo7seygePzIkr37ZCeaW2hmZ-c6v_c7Yp3Y0kzE5OE0h93J09XAtYfwZk3zZVKXH8hd6fWjeY7ZgB8I4CpQaa9BX-Zp9bBznXHh5WqpckkMAXZVT-wiLNVqQDpyg8Jifi5tuw4SjT4irRrFYF5LfSDLU4EigKKC3Rn1IOlwEKhHuvqLFuCbqgXVh_Ps75P9_wXr3XoKSwEDf5zbOh42cPlenKfG0TQpeEhKamEbmpuRnOZYRHmOQ0d6KTI7t8xxRQ0g3nF0AJGQKwnbZDgZPli8v3dI8XZY9rca03rG8aQpCag.JFWISQTeuw2euVfT.5ekMlQk5tkPFLdUnZIh-GMfFGS36UPKAd_obtu-YCy_vv_iuNPVbxZyzjJFRnK2-G8Cf3UuKvpNusyjpd_AfIvoxg7fqCr95CZ8IulBGo1SddvcXx-kCsCNPawK97pN7qclHc6oqrIpK4CjUR0msJtgNbdTrFI0VOw1dLXoz_jFJ13xO1LQiXkxdJltD6qpEfE3x1UyNFpDHudplur7v6cd9WOXNFlQ6zQYfn-9ZHOMGoGFcQAB9u9crCkoyIX4vifNrJA.zD8126ElxZvp-RODUr5qSg";
String jwtStringNew = "eyJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.wDiB-oEawb6cBHUyHT-_LVtRwaA7bwL8qwoqXGYayXae6EFr6wKIP2M5woq9HSGWRFH48JIyNS6V_K3MdXfh9oqjVd3djBeUKtcP6b-2jWjFxLL-WOgZpHmSMpWhOB55ogKQRumo0YYn4HMd8JrQ48uYGa7NoWOxMIBajKNu4utkOW-1q-ccbN4_6mds90brEJDnlbcHyo22sjufiXeKhN8_JaN6uqx3qet08ouhEEOaFhssj7nyP3ynz75rT17iw_VAoS91JP6lb-Q4T4ZsA_9_ibZUZn4vkk1mWU0Kul2Hp0z5GXw_ZPNi7IsTv0D4xvDnWmwTUb3ekdj0cCYmMg.e0w_dONIFxka8bXU.bEAl8JYqj-4xSlC1i4xXSbdMqBz61TuKUHdYq46L2_vxTpTjh04o5juH4eDbs6cfEgGy.44dOKOY7h-Hg27OnHxIBsg";
EncryptedJWT jwt1= EncryptedJWT.parse(jwtStringNew);
// Create a decrypter with the specified private RSA key
RSADecrypter decrypter = new RSADecrypter(privKey);
// Decrypt
jwt1.decrypt(decrypter);
System.out.println(jwt1.getHeader());
System.out.println("numbusJWe::: "+jwt1.getPayload());
// TODO Auto-generated method stub
}
private static String jose4JEcnryption(PublicKey key) throws JoseException {
JsonWebEncryption jwe = new JsonWebEncryption();
jwe.setPayload("Hello World!");
jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.RSA_OAEP_256);
jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_256_GCM);
jwe.setKey(key);
String serializedJwe = jwe.getCompactSerialization();
System.out.println("Serialized Encrypted JWE: " + serializedJwe);
return serializedJwe;
}
private static void jose4JDeryption(PrivateKey key, String jweToken) throws JoseException {
String jwtStringNew1 = "eyJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.wDiB-oEawb6cBHUyHT-_LVtRwaA7bwL8qwoqXGYayXae6EFr6wKIP2M5woq9HSGWRFH48JIyNS6V_K3MdXfh9oqjVd3djBeUKtcP6b-2jWjFxLL-WOgZpHmSMpWhOB55ogKQRumo0YYn4HMd8JrQ48uYGa7NoWOxMIBajKNu4utkOW-1q-ccbN4_6mds90brEJDnlbcHyo22sjufiXeKhN8_JaN6uqx3qet08ouhEEOaFhssj7nyP3ynz75rT17iw_VAoS91JP6lb-Q4T4ZsA_9_ibZUZn4vkk1mWU0Kul2Hp0z5GXw_ZPNi7IsTv0D4xvDnWmwTUb3ekdj0cCYmMg.e0w_dONIFxka8bXU.bEAl8JYqj-4xSlC1i4xXSbdMqBz61TuKUHdYq46L2_vxTpTjh04o5juH4eDbs6cfEgGy.44dOKOY7h-Hg27OnHxIBsg";
JsonWebEncryption jwe = new JsonWebEncryption();
jwe.setAlgorithmConstraints(new AlgorithmConstraints(ConstraintType.PERMIT,
KeyManagementAlgorithmIdentifiers.RSA_OAEP_256));
jwe.setContentEncryptionAlgorithmConstraints(new AlgorithmConstraints(ConstraintType.PERMIT,
ContentEncryptionAlgorithmIdentifiers.AES_256_GCM));
jwe.setKey(key);
jwe.setCompactSerialization(jwtStringNew1);
System.out.println("JOSE4J ::: getHeaders :::: " + jwe.getHeaders());
System.out.println("JOSE4J ::: getContentEncryptionAlgorithm :::: " + jwe.getContentEncryptionAlgorithm());
System.out.println("JOSE4J ::: getEncryptedKey :::: " + jwe.getEncryptedKey());
System.out.println("JOSE4J ::: getIv :::: " + jwe.getIv());
System.out.println("JOSE4J ::: Payload :::: " + jwe.getPayload());
}
I have to implement a dart algorithm in order to encrypt a password and send it to a server for authentication from a flutter app (it's barely a week since I'm on flutter/dart). This has already been implemented in an android app and angular web app (not from me), which both produce the same encrypted password even though with different algorithms.
Java code for android:
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.CryptoPrimitive;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;
public class AesUtil {
private final int keySize;
private final int iterationCount;
private final Cipher cipher;
public AesUtil(int keySize, int iterationCount) {
this.keySize = keySize;
this.iterationCount = iterationCount;
try {
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw fail(e);
}
}
public String decrypt(String salt, String iv, String passphrase, String ciphertext) {
try {
SecretKey key = generateKey(salt, passphrase);
byte[] decrypted = doFinal(Cipher.DECRYPT_MODE, key, iv, base64(ciphertext));
return new String(decrypted, "UTF-8");
} catch (UnsupportedEncodingException e) {
return null;
} catch (Exception e) {
return null;
}
}
private byte[] doFinal(int encryptMode, SecretKey key, String iv, byte[] bytes) {
try {
cipher.init(encryptMode, key, new IvParameterSpec(hex(iv)));
return cipher.doFinal(bytes);
} catch (InvalidKeyException
| InvalidAlgorithmParameterException
| IllegalBlockSizeException
| BadPaddingException e) {
return null;
}
}
private SecretKey generateKey(String salt, String passphrase) {
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), hex(salt), iterationCount, keySize);
SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
return key;
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
return null;
}
}
public static byte[] base64(String str) {
return Base64.decode(str);
}
public static String base64(byte[] bytes) {
return new String(Base64.encode(bytes));
}
public static byte[] hex(String str) {
try {
return Hex.decode(str);
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
public static String hex(byte[] bytes) {
return Hex.encode(bytes).toString();
}
private IllegalStateException fail(Exception e) {
return null;
}
public String random(int length) {
byte[] salt = new byte[length];
new SecureRandom().nextBytes(salt);
return hex(salt);
}
public String encrypt(String salt, String iv, String passphrase, String plaintext) {
try {
SecretKey key = generateKey(salt, passphrase);
byte[] encrypted = doFinal(Cipher.ENCRYPT_MODE, key, iv, plaintext.getBytes("UTF-8"));
return base64(encrypted);
} catch (UnsupportedEncodingException e) {
throw fail(e);
}
}
public String encriptToAES(String password) {
//`
//for some reasons key, iv and salt are hardcoded string
//
final String key = "hardcoded_key_16_characters";
final String iv = "hardcoded_iv_32_characters";
final String salt = "hardcoded_salt_32_characters";
String ciphertext = encrypt(salt, iv, key, password);
String preEncr = new String(Base64.encode((iv + "::" + salt + "::" + ciphertext).getBytes()));
return preEncr;
}
}
And this is the java line of code which generate the encrypted password:
AesUtil(128, 1000).encriptToAES(password)
JS code for angular:
import * as CryptoJS from 'crypto-js';
export class AesUtil{
private keySize;
private iterationCount;
constructor(keySize, iterationCount) {
this.keySize = keySize / 32;
this.iterationCount = iterationCount;
};
generateKey(salt, passPhrase) {
var key = CryptoJS.PBKDF2(
passPhrase,
CryptoJS.enc.Hex.parse(salt),
{ keySize: this.keySize, iterations: this.iterationCount });
return key;
}
encrypt(salt, iv, passPhrase, plainText) {
var key = this.generateKey(salt, passPhrase);
var encrypted = CryptoJS.AES.encrypt(
plainText,
key,
{ iv: CryptoJS.enc.Hex.parse(iv) });
return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
}
decrypt(salt, iv, passPhrase, cipherText) {
var key = this.generateKey(salt, passPhrase);
var cipherParams = CryptoJS.lib.CipherParams.create({
ciphertext: CryptoJS.enc.Base64.parse(cipherText)
});
var decrypted = CryptoJS.AES.decrypt(
cipherParams,
key,
{ iv: CryptoJS.enc.Hex.parse(iv) });
return decrypted.toString(CryptoJS.enc.Utf8);
}
}
And this code does the trick:
const iv = CryptoJS.lib.WordArray.random(128/8).toString(CryptoJS.enc.Hex);
const salt = CryptoJS.lib.WordArray.random(128/8).toString(CryptoJS.enc.Hex);
const aesUtil = newAesUtil(128,1000);
const cipherText = aesUtils.encrypt(salt,iv,'hardcoded_key_16_characters',password);
const aesPassword = (iv+ '::' + salt + '::'+ cipherText);
const encryptedPassword = btoa(aesPassword);
For what I can understand I need an AES128 encryption method, where to set a specific number of iterations, which accepts iv and salt and eventually encrypt the result with Base64.
I have already tried all kinds of dart encryption packages on pub.dev and snippets without success.
I was relying on this one in particular, but even with hardcoded parameters the result password doesn't match and I'm not able to figure out why. Does anyone know on which elements I have to focus in order to achieve the same result in flutter? For example, which aes128 'plugin' should I use? Static or random iv and salt? All kind of things, I'm pretty much lost. Thanks
UPDATE:
import 'dart:typed_data';
import 'dart:convert';
import 'package:cryptography/cryptography.dart';
final password = "justatest";
final key = "0123456789abcdef";
final iv = "0123456789abcdefghijklmnopqrstuv";
final salt = "abcdefghijklmnopqrstuvwzyz012345";
encryptAESCryptoJS() {
final pbkdf2 = Pbkdf2(
macAlgorithm: Hmac(sha1),
iterations: 1000,
bits: 128,
);
final Uint8List hashBytes = pbkdf2.deriveBitsSync(
utf8.encode(key),
nonce: Nonce(utf8.encode(salt)),
);
}
I have a c# dll registered in regasm.exe and I am trying to call it on my classic asp application below is my code part:
I am sending a dictionary object as parameter to the function
Dim parameters
Set parameters=Server.CreateObject("Scripting.Dictionary")
For Each Item1 In Request.Form
fieldName = Item1
fieldValue = Request.Form(Item1)
parameters.Add fieldName, fieldValue
Next
Here is where I am calling the function
Set CudExternal=Server.Createobject("CudExternal.Security")
Set signature = CudExternal.sign(parameters)
When I try to call the function I am getting this error.
Below is my dll code:
public class Security
{
private const String SECRET_KEY = "dd6b7d26fb0c4db7891b28718a1a468";
public string sign(IDictionary<string, string> paramsArray)
{
return sign(buildDataToSign(paramsArray), SECRET_KEY);
}
private string sign(String data, String secretKey)
{
UTF8Encoding encoding = new System.Text.UTF8Encoding();
byte[] keyByte = encoding.GetBytes(secretKey);
HMACSHA256 hmacsha256 = new HMACSHA256(keyByte);
byte[] messageBytes = encoding.GetBytes(data);
return Convert.ToBase64String(hmacsha256.ComputeHash(messageBytes));
}
private string buildDataToSign(IDictionary<string, string> paramsArray)
{
String[] signedFieldNames = paramsArray["signed_field_names"].Split(',');
IList<string> dataToSign = new List<string>();
foreach (String signedFieldName in signedFieldNames)
{
dataToSign.Add(signedFieldName + "=" + paramsArray[signedFieldName]);
}
return commaSeparate(dataToSign);
}
private string commaSeparate(IList<string> dataToSign)
{
return String.Join(",", dataToSign);
}
public string outputr(string data)
{
return data;
}
}
How can I Resolve??...Thanks in Advance.
Have such desktop application
it seems work but finally as token return encrypted saml
could you prompt me how to decrypt it
class Program
{
static void Main(string[] args)
{
ServicePointManager.ServerCertificateValidationCallback += RemoteCertificateValidationCallback;
var samlToken = GetSamlToken("#domain", "#login", "#password");
Console.WriteLine(Uri.UnescapeDataString(samlToken));
Console.ReadLine();
}
private static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return sslPolicyErrors == SslPolicyErrors.None
|| string.Equals(certificate.Issuer, "CN=Name", StringComparison.InvariantCultureIgnoreCase);
}
private static string GetSamlToken(string domain, string userName, string password)
{
var acsUrl = "#RPURL";
var stsUrl = "#stsurl";
WSTrustChannelFactory trustChannelFactory =
new WSTrustChannelFactory(new WindowsWSTrustBinding(SecurityMode.TransportWithMessageCredential),
new EndpointAddress(new Uri(stsUrl)));
trustChannelFactory.TrustVersion = TrustVersion.WSTrust13;
trustChannelFactory.Credentials.Windows.ClientCredential.Domain = domain;
trustChannelFactory.Credentials.Windows.ClientCredential.UserName = userName;
trustChannelFactory.Credentials.Windows.ClientCredential.Password = password;
try
{
RequestSecurityToken rst =
new RequestSecurityToken(WSTrust13Constants.RequestTypes.Issue, WSTrust13Constants.KeyTypes.Bearer);
rst.AppliesTo = new EndpointAddress(acsUrl);
rst.TokenType = Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml2TokenProfile11;
WSTrustChannel channel = (WSTrustChannel)trustChannelFactory.CreateChannel();
GenericXmlSecurityToken token = channel.Issue(rst) as GenericXmlSecurityToken;
string tokenString = token.TokenXml.OuterXml;
return tokenString;
}
finally
{
trustChannelFactory.Close();
}
}
}
thanks
check http://zamd.net/category/federationsts/