CryptoJS Encryption (AES) - reactjs

my Code is written in Java, I want to use it into react-native, but I am not able to convert it properly in react native, I am stuck in it from last 36 hours.
I am able to encrypt the code , but the apis are written and I have to create a replica of android app.
input is : api/v1/master/Login/PinAuthentication
expected output is : BiR6DnP2PDlLRiRxlaqzK/p+ysGnvL6SF2SCZEN/UbIBQwJ/eDQT8uLuZffcT+kl
my react.js code is :
var CryptoJS = require("crypto-js");
let workingURL = "BiR6DnP2PDlLRiRxlaqzK%2Fp%2BysGnvL6SF2SCZEN%2FUbIBQwJ%2FeDQT8uLuZffcT%2Bkl"
let decryptedText = "BiR6DnP2PDlLRiRxlaqzK/p+ysGnvL6SF2SCZEN/UbIBQwJ/eDQT8uLuZffcT+kl"
let appstring = "api/v1/master/Login/PinAuthentication"
let appkey = "****************************************"
//JFACzfbeLzsha7vB5vl3QMgnl3iYX06LWb3tjjnNTYQkV8ZMFg+xEtxY/uM8vEZk
function encrypt10(){
let ciphertext = CryptoJS.enc.Utf8.parse(appstring)
let secSpec = [-53, -96, -53, -96, -53, -92, -52, -95, -54, -92, -54, -91, -54, -88, -54, -89]
let ivSpec = [-53, -96, -53, -96, -53, -92, -52, -95, -54, -92, -54, -91, -54, -88, -54, -89]
ivSpec = CryptoJS.enc.Utf8.parse(appkey)
secSpec = CryptoJS.enc.Utf8.parse(appkey)
console.log("ciphertext : " + ciphertext)
console.log("secSpec : " + secSpec)
console.log("ivSpec : " + ivSpec)
var encrypted = CryptoJS.AES.encrypt(ciphertext, secSpec, {
iv: ivSpec, //yes I used password as iv too. Dont mind.
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
keySize: 128 / 8,
});
console.log(encrypted.toString());
}
to test it I am using react-js because of crypto-js library.
private static byte[] getKeyBytes() throws UnsupportedEncodingException {
byte[] keyBytes = new byte[16];
byte[] parameterKeyBytes = KEY.getBytes("UTF-8");
System.arraycopy(parameterKeyBytes, 0, keyBytes, 0, Math.min(parameterKeyBytes.length, keyBytes.length));
return keyBytes;
}
public static byte[] encrypt2(String value){
try{
byte[] keyBytes = getKeyBytes();
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec myKey = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec IVKey = new IvParameterSpec(keyBytes);
cipher.init(Cipher.ENCRYPT_MODE, myKey, IVKey);
byte[] outputBytes = cipher.doFinal(value.getBytes("UTF-8"));
return outputBytes;
}catch(Exception err){
err.printStackTrace();
return null;
}
}

The main problem seems to me to be the derivation of the key.
The Java code performs a UTF8 encoding of KEY and then uses the first 16 bytes as key. In the CryptoJS code, you also perform a UTF8 encoding of appkey (with CryptoJS.enc.Utf8.parse()), but then apply the entire data as key.
You need to shorten the data, e.g. with secSpec.words.slice(0, 16/4)) and analogously for ivSpec, since you use the key as IV, which is insecure by the way.
With this change, encryption works with the CryptoJS code and the ciphertext matches the expected result / the result of the Java Code (for the true key):
let appstring = "api/v1/master/Login/PinAuthentication";
let appkey = "****************************************";
function encrypt10(){
let plaintext = CryptoJS.enc.Utf8.parse(appstring);
let secSpec = CryptoJS.enc.Utf8.parse(appkey);
let ivSpec = CryptoJS.enc.Utf8.parse(appkey);
secSpec = CryptoJS.lib.WordArray.create(secSpec.words.slice(0, 16/4));
ivSpec = CryptoJS.lib.WordArray.create(ivSpec.words.slice(0, 16/4));
var encrypted = CryptoJS.AES.encrypt(plaintext, secSpec, {iv: ivSpec});
document.getElementById("ct").innerHTML = encrypted.toString();
}
encrypt10();
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
<p style="font-family:'Courier New', monospace;" id="ct"></p>
Regarding the key: More robust than a UTF8 decoding is a binary-to-text encoding like Base64 or hex.

Related

Error: The argument type 'List<int>' can't be assigned to the parameter type 'Uint8List'

Below is my original codes run well without problem under flutter version 1.22.6, however when I upgraded to flutter version 2.2.1 error of "The argument type 'List' can't be assigned to the parameter type 'Uint8List'." flagged with red error:
final paint = await PaintingBinding.instance!
.instantiateImageCodec(asset != null ? img.encodePng(asset) : buffer);
Anyone could help will be much appreaciated.
This my code:
Future<BeautifulPopup> recolor(Color color) async {
primaryColor = color;
final illustrationData = await rootBundle.load(instance.illustrationKey);
final buffer = illustrationData.buffer.asUint8List();
img.Image asset;
asset = img.readPng(buffer)!;
img.adjustColor(
asset,
saturation: 0,
// hue: 0,
);
img.colorOffset(
asset,
red: primaryColor.red,
// I don't know why the effect is nicer with the number ╮(╯▽╰)╭
green: primaryColor.green ~/ 3,
blue: primaryColor.blue ~/ 2,
alpha: 0,
);
final paint = await PaintingBinding.instance!
.instantiateImageCodec(asset != null ? img.encodePng(asset) : buffer);
final nextFrame = await paint.getNextFrame();
_illustration = nextFrame.image;
return this;
}
...
This is because they are different types. But here is an easy way to handle the conversion:
Uint8List uint8List;
List<int> list;
// convert List<int> to Uint8List.
uint8List = Uint8List.fromList(list);
// convert Uint8List to List<int>
list = List<int>.from(uint8List);
Cheers!
David

EncodedImage failing to work on actual phone

I am facing a problem while using encodedImage. When a user logins into the app, the first form after successful login has an image. And the image is causing me issues upon retrieving it.
When the user captures an image in the app, I convert it to a base64 string which I send to the server. The code for that is:
ImageIO img = ImageIO.getImageIO();
ByteArrayOutputStream out = new ByteArrayOutputStream();
img.save(et, out, ImageIO.FORMAT_JPEG, 1);
byte[] ba = out.toByteArray();
String userImage64 = Base64.encodeNoNewline(ba);
et is the captured image. So I store the string userImage64 in the server.
When I retrieve the base64, I decode it and convert it to an EncodedImage. The code is:
String url = new JSONObject(result.getResponseData()).getString("photo");
byte[] b = Base64.decode(url.getBytes());
Image icon = EncodedImage.create(b);
When I am on the simulator, everything flows smoothly. The images display and everything works very well.
My issue is, when I put the app on an android device, it doesn't work. It shows me a toast of successful login and just stops there. So i did some debugging and realized that issue is with the three lines of converting from base64 to image. When I comment out the three lines, everything works very well. Where could I be going wrong?
EDIT
Below is the code I use to capture a photo:
String i = Capture.capturePhoto();
if (i != null) {
try {
final Image newImage = Image.createImage(i);
Image roundedMask = Image.createImage(rich.minScreensize() / 4, rich.minScreensize() / 4, 0xff000000);
Graphics gra = roundedMask.getGraphics();
gra.setColor(0xffffff);
gra.fillArc(0, 0, rich.minScreensize() / 4, rich.minScreensize() / 4, 0, 360);
Object masked = roundedMask.createMask();
cropImage(newImage, rich.minScreensize() / 4, rich.minScreensize() / 4, et -> {
if (editing) {
try {
ImageIO img = ImageIO.getImageIO();
ByteArrayOutputStream out = new ByteArrayOutputStream();
img.save(et, out, ImageIO.FORMAT_JPEG, 1);
byte[] ba = out.toByteArray();
userImage64 = Base64.encodeNoNewline(ba);
et = et.applyMask(masked);
logoimage.setIcon(et);
///removed unnecessary code
logoimage.getComponentForm().revalidate();
} catch (IOException ex) {
}
} else {
et = et.applyMask(masked);
logoimage.setIcon(et);
}
});
} catch (IOException ex) {
Log.p("Error loading captured image from camera", Log.ERROR);
}
}
Inside there is code I use to crop the photo and that is code is:
private void cropImage(Image img, int destWidth, int destHeight, OnComplete<Image> s) {
Form previous = getCurrentForm();
Form cropForm = new Form("", new LayeredLayout());
Label toobarLabel = new Label("New Holder", "Toolbar-HeaderLabel");
cropForm.setTitleComponent(toobarLabel);
Toolbar mainToolbar = new Toolbar();
mainToolbar.setUIID("ToolBar");
cropForm.setToolbar(mainToolbar);
Label moveAndZoom = new Label("Move and zoom the photo to crop it");
moveAndZoom.getUnselectedStyle().setFgColor(0xffffff);
moveAndZoom.getUnselectedStyle().setAlignment(CENTER);
moveAndZoom.setCellRenderer(true);
cropForm.setGlassPane((Graphics g, Rectangle rect) -> {
g.setColor(0x0000ff);
g.setAlpha(150);
Container cropCp = cropForm.getContentPane();
int posY = cropForm.getContentPane().getAbsoluteY();
GeneralPath p = new GeneralPath();
p.setRect(new Rectangle(0, posY, cropCp.getWidth(), cropCp.getHeight()), null);
if (isPortrait()) {
p.arc(0, posY + cropCp.getHeight() / 2 - cropCp.getWidth() / 2,
cropCp.getWidth() - 1, cropCp.getWidth() - 1, 0, Math.PI * 2);
} else {
p.arc(cropCp.getWidth() / 2 - cropCp.getHeight() / 2, posY,
cropCp.getHeight() - 1, cropCp.getHeight() - 1, 0, Math.PI * 2);
}
g.fillShape(p);
g.setAlpha(255);
g.setColor(0xffffff);
moveAndZoom.setX(0);
moveAndZoom.setY(posY);
moveAndZoom.setWidth(cropCp.getWidth());
moveAndZoom.setHeight(moveAndZoom.getPreferredH());
moveAndZoom.paint(g);
});
final ImageViewer viewer = new ImageViewer();
viewer.setImage(img);
cropForm.add(viewer);
cropForm.getToolbar().addMaterialCommandToRightBar("", FontImage.MATERIAL_CROP, e -> {
previous.showBack();
s.completed(viewer.getCroppedImage(0).
fill(destWidth, destHeight));
});
cropForm.getToolbar().addMaterialCommandToLeftBar("", FontImage.MATERIAL_CANCEL, e -> previous.showBack());
cropForm.show();
}

How to do the correct way to encrypt to AES256 using CryptoJs

Hi i'm new to React Native,
i can encrypt the data in the PHP but not with React Native using Crypto JS. (result in JS always different, the correct one is from the PHP)
This is the example in PHP :
<?php
$data = 'my1234567';
$iv = 'yourivare1234567';
$key = '356d9abc7532ceb0945b615a622c3370';
$abc = openssl_encrypt($data, 'aes-256-cbc', $key, 0, $iv);
var_dump($abc);
// result is : string(24) "9EF/QLpR+o/KrVueiI4L0g=="
Now i try to replicate it in my React Native apps using Crypto JS.
But the result always different, where i'm expecting the result using hardcoded data and iv like above is : "9EF/QLpR+o/KrVueiI4L0g=="
Below is the source code in JS :
const data = 'my1234567';
const iv = 'yourivare1234567';
const key = '356d9abc7532ceb0945b615a622c3370';
const fkey = CryptoJS.enc.Hex.parse(key);
const fiv = CryptoJS.enc.Hex.parse(iv);
const enc = CryptoJS.AES.encrypt(data, md5key, {
iv: fiv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
});
const final = enc.ciphertext.toString(CryptoJS.enc.Base64);
console.log('encrypted password: ' , final) // result is kYLFiwI1IDZcFfsKsbrbzg==
Can somebody help on this?
Thanks before
fkey and fiv must be parsed using the UTF8 encoder. md5key is not defined and must be replaced by fkey:
const data = 'my1234567';
const iv = 'yourivare1234567';
const key = '356d9abc7532ceb0945b615a622c3370';
const fkey = CryptoJS.enc.Utf8.parse(key);
const fiv = CryptoJS.enc.Utf8.parse(iv);
const enc = CryptoJS.AES.encrypt(data, fkey, {
iv: fiv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
});
const final = enc.ciphertext.toString(CryptoJS.enc.Base64);
console.log('encrypted password: ' , final) // result is 9EF/QLpR+o/KrVueiI4L0g==
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
Note that (except for testing purposes) no static IV may be used for security reasons.

Coinbase body format

My goal is to send a Post request by using Coinbase API.
In the documentation (coinbase), it is specified that the body of the request should be added to the prehash string for message signature.
I am wondering what is the format of this body that I have to sent. Possible way I think I could do that :
concatenation of only the values value1+value2+value3
key=value seperated with &
other way ?
The body should just be a stringified JSON added to the timestamp, method, and path, respectively. Here's the example from the docs:
var crypto = require('crypto');
var secret = 'PYPd1Hv4J6/7x...';
var timestamp = Date.now() / 1000;
var requestPath = '/orders';
var body = JSON.stringify({
price: '1.0',
size: '1.0',
side: 'buy',
product_id: 'BTC-USD'
});
var method = 'POST';
// create the prehash string by concatenating required parts
var what = timestamp + method + requestPath + body;
// decode the base64 secret
var key = Buffer(secret, 'base64');
// create a sha256 hmac with the secret
var hmac = crypto.createHmac('sha256', key);
// sign the require message with the hmac
// and finally base64 encode the result
return hmac.update(what).digest('base64');

windows phone create database with items

I am building a simple application for windows phone. I want to create a database and want to have several (lets say 10) items in the database. I am a beginner and every tutorial that i have seen is sth about adding items in the database on button "add" or sth like that. I don't need that, because I want to have several item that are in the database, ready for the user to use them. How can I achieve this? Please write to me in a clear way, because I am still a beginner. If you can provide some links of examples or tutorials, that would be great. Thank u!
If you need to have the preloaded DB then you can Add a sqlCe DB in your application and populate the db with your seed Data.
then you can copy the DB file to your ISO Store while your Constructor of DBContext is invoked.
public Moviadb1DataContext (string connectionString) : base(connectionString)
{
IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication();
if (!iso.FileExists("Moviadb1.sdf"))
{
MoveReferenceDatabase();
}
if (!DatabaseExists())
CreateDatabase();
}
public static void MoveReferenceDatabase()
{
// Obtain the virtual store for the application.
IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication();
// Create a stream for the file in the installation folder.
using (Stream input = Application.GetResourceStream(new Uri("Moviadb1.sdf", UriKind.Relative)).Stream)
{
// Create a stream for the new file in isolated storage.
using (IsolatedStorageFileStream output = iso.CreateFile("Moviadb1.sdf"))
{
// Initialize the buffer.
byte[] readBuffer = new byte[4096];
int bytesRead = -1;
// Copy the file from the installation folder to isolated storage.
while ((bytesRead = input.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
output.Write(readBuffer, 0, bytesRead);
}
}
}
}
you can also add some seed data instead of moving the reference DB if you have very small amount of Data.
public ListenDataDataContext (string connectionString) : base(connectionString)
{
if (!DatabaseExists())
{
CreateDatabase();
List<Audiables> PreLoads = new List<Audiables>();
PreLoads.Add(new Audiables { Category = 1, Name = "I want To Eat", AudioLocation = "Sounds/Food/1_IwantToEat.wma", ImageLocation = "Images/Food/1_IwantToEat.jpg" });
PreLoads.Add(new Audiables { Category = 1, Name = "I want To Drink", AudioLocation = "Sounds/Food/1_IwantToDrink.wma", ImageLocation = "Images/Food/1_IwantToDrink.jpg" });
PreLoads.Add(new Audiables { Category = 2, Name = "I want A Ticket", AudioLocation = "Sounds/Travel/1_IwantATicket.wma", ImageLocation = "Images/Travel/1_IwantATicket.jpg" });
PreLoads.Add(new Audiables { Category = 2, Name = "I want To Sit", AudioLocation = "Sounds/Travel/1_IwantToSit.wma", ImageLocation = "Images/Travel/1_IwantToSit.jpg" });
PreLoads.Add(new Audiables { Category = 3, Name = "How Much Is That", AudioLocation = "Sounds/Shopping/1_HowMuchIsThat.wma", ImageLocation = "Images/Shopping/1_HowMuchIsThat.jpg" });
PreLoads.Add(new Audiables { Category = 3, Name = "Please Take the Money", AudioLocation = "Sounds/Shopping/1_PleaseTakeTheMoney.wma", ImageLocation = "Images/Shopping/1_PleaseTakeTheMoney.jpg" });
Audiables.InsertAllOnSubmit(PreLoads);
this.SubmitChanges();
}
}
Happy app making :)
Best way is to check the "Local Database Sample" in the Windows Phone Code Samples!

Resources