I am trying to use pointycastle package to decrypt a message using the below code
static String decrypt(String password, String ciphertext}) {
Uint8List derivedKey = deriveKey(password);
KeyParameter keyParam = KeyParameter(derivedKey);
BlockCipher aes = AESFastEngine();
Uint8List cipherIvBytes = base64.decode(ciphertext);
Uint8List iv =
Uint8List.fromList(HEX.decode("a4094fd5d6041eb3a7a77d7fa73ea329"))
..setRange(0, aes.blockSize, cipherIvBytes);
BlockCipher cipher = CBCBlockCipher(aes);
ParametersWithIV params = ParametersWithIV(keyParam, iv);
cipher.init(false, params);
int cipherLen = cipherIvBytes.length - aes.blockSize;
Uint8List cipherBytes = Uint8List(cipherLen)
..setRange(0, cipherLen, cipherIvBytes, aes.blockSize);
Uint8List paddedText = _processBlocks(cipher, cipherBytes);
log('before padding'); //works until this point
Uint8List textBytes = unpad(paddedText);
log(String.fromCharCodes(textBytes));
return String.fromCharCodes(textBytes);
}
below are the functions for _processBlocks and unpad
static Uint8List _processBlocks(BlockCipher cipher, Uint8List inp) {
var out = Uint8List(inp.lengthInBytes);
for (var offset = 0; offset < inp.lengthInBytes;) {
var len = cipher.processBlock(inp, offset, out, offset);
offset += len;
}
return out;
}
static Uint8List unpad(Uint8List src) {
var pad = PKCS7Padding();
pad.init(null);
int padLength = pad.padCount(src);
int len = src.length - padLength;
return Uint8List(len)..setRange(0, len, src);
}
My problem is when I try to decrypt the message I have it show me this error
Invalid argument(s): Invalid or corrupted pad block
this is a sample key and message
key : CE6C4B509712CAA6237B336A517B4245
message : pAlP1dYEHrOnp31/pz6jKSOBf/UwAYc31WqbPBhCGjXeMGfjxWqb8IC7U3yS/niViwhlot8vvMVGR9DvV9+Rchy3tsABb4NczP88JpfL8S9ifNGBc+d8dvOGFyB2K5cXLLaiTqA+ReEHbRtp0bOjisb/krwIzafnU3OaIbhl/nnsWmuhdpqNNem1ZPkrdhCMuQrdad6pU6cvg0yLdMZ6Z8PQUOoJ8e64n53Q4j88Gtey71cOt/vwW8aUlUbgG1D0tyu2VlWat5IAn5/AutX88Pu20YX9s3MPf4AAe5U40FKm34PerYzj3DjZX7/fafjoIIh4AZ1Vva36ooI2kF2GFsHbUpbOMUa5Gz61aca4wm0Jq7KdUH4GhMLkMCCEF+C5JPsRBnCo3Ickh3YZTHWbmy/63F7chcrqd8fxOCNMqqeaQhakFdeEIao47gpb62OLtpjTytLQgQ1rYjdbA+vdqdOy1ZV0CIepIRfNAy4Bge5ifMQLyaG2wha3GKO+f6+c7qmwSNAGY/mxKHNQP/eHemMf/uNOSiOE32IZ29L+3/Ckajgk+uOuO6xgBIAMzP40Eqh0l7uvZgbRUbt5Ws2Fw8QpnoOm0S2T2koA0MZPISaJdE5Gzdmfk5gxGVtOkEUqTMw69xAN7eMYHTd5cW6bbjEefijgH15GtgkzUXJb7LPDYO+rnwTHprHg/JRxeFzDnYQn9VjlBDCYzKa41qjo/Q==
What could be the problem here. And what are the possible solutions or workarounds for this error. Thanks in advance.
Related
I try to calculate the average color from SVG format Image, but I don't know how can an SVG Image from the network convert to Unit8List, ImageProvider, or BitMap!
for any of these types that I say, I can calculate the average color with the below code :
(I use image package)
import 'package:image/image.dart' as imgPack;
//
Unit8List _myHunit8List = ...
imgPack.Image bitmap = imgPack.decodeImage(_myHunit8List );
int redBucket = 0;
int greenBucket = 0;
int blueBucket = 0;
int pixelCount = 0;
for (int y = 0; y < bitmap.height; y++) {
for (int x = 0; x < bitmap.width; x++) {
int c = bitmap.getPixel(x, y);
pixelCount++;
redBucket += img.getRed(c);
greenBucket += img.getGreen(c);
blueBucket += img.getBlue(c);
}
}
Color averageColor = Color.fromRGBO(redBucket ~/ pixelCount,
greenBucket ~/ pixelCount, blueBucket ~/ pixelCount, 1);
how can I an SVG Image from the network
( I use flutter_svg package like:
SvgPicture.network(url);
) convert to Unit8List ?
It transfers from Image url to Uint8List.
Future<Uint8List> getUint8ListFromImage(imgUrl) async {
Uint8List bytes = (await NetworkAssetBundle(Uri.parse(imgUrl)).load(imgUrl))
.buffer
.asUint8List();
print(bytes);
return bytes;
}
you can convert network image to file and then you can easily convert file to uint8List,
convert image url to file
Future<File> urlToFile(String imageUrl) async {
// generate random number.
var rng = new Random();
// get temporary directory of device.
Directory tempDir = await getTemporaryDirectory();
// get temporary path from temporary directory.
String tempPath = tempDir.path;
// create a new file in temporary path with random file name.
File file = new File('$tempPath'+ (rng.nextInt(100)).toString() +'.svg');
// call http.get method and pass imageUrl into it to get response.
http.Response response = await http.get(imageUrl);
// write bodyBytes received in response to file.
await file.writeAsBytes(response.bodyBytes);
// now return the file which is created with random name in
// temporary directory and image bytes from response is written to // that file.
return file;
}
The problem is while using the camera and passing frames by ImageStream,
I keep getting src->data == nullptr from the c++ code (OpenCV) while invoking the imdecode function. How come?
I have debugged the issue and I have found out in the getByte function,
I get:
img.height = 480
img.width = 720
In my opinion each plane should be of length 345600 (480*720)
but I got:
img.planes[0].bytes.length = 368592
img.planes[1].bytes.length = 184271
img.planes[2].bytes.length = 184271
How can it be the image's planes don't have the same length??
The following block is from the flutter app:
initCamera() {
cameraController = CameraController(cameras[0], ResolutionPreset.medium);
cameraController.initialize().then((value) {
if (!mounted) return;
setState(() {
cameraController.startImageStream((imageStream) {
cameraImage = imageStream;
print("Frame number: $frameCounter");
frameCounter++;
res = imageMetaData.applyConvertToMatrix(cameraImage);
// runModel();
});
});
});
}
Calling the c++ code by ffi:
Uint8List getBytes(CameraImage img) {
final WriteBuffer allBytes = WriteBuffer();
//Write all the values from a Uint8List into the buffer.
img.planes.forEach((plane) => allBytes.putUint8List(plane.bytes));
return allBytes.done().buffer.asUint8List();
}
Pointer<Uint8> intListToArray(Uint8List list) {
final Pointer<Uint8> ptr = calloc.allocate<Uint8>(list.length);
for (var i = 0; i < list.length; i++) {
ptr.elementAt(i).value = list[i];
}
return ptr;
}
Future<bool> applyConvertToMatrix(CameraImage img) async {
func_convert_to_matrix = nativeAddLib.lookup<NativeFunction<Pointer<Void> Function(
Pointer<Uint8>, Pointer<Int32>)>>("convert_from_img_array_to_matrix")
.asFunction();
Uint8List bytes = getBytes(img);
Pointer<void> ptr;
Pointer<Uint8> imgBytes;
imgByteLength.value = bytes.length;
imgBytes = intListToArray(bytes);
ptr = func_convert_to_matrix(imgBytes, imgByteLength); //invoking the c++ code
return true;
}
The C++ code:
void *convert_from_img_array_to_matrix(
unsigned char *img,
int32_t *imgLengthBytes) {
cv::Mat *src = new Mat();
int32_t len_bytes = *imgLengthBytes;
std::vector<unsigned char> m;
__android_log_print(ANDROID_LOG_VERBOSE, "NATIVE", "Len bytes: %d", len_bytes);
while ( len_bytes>=0 )
{
m.push_back(*(img++));
len_bytes--;
}
*src = cv::imdecode(m, cv::IMREAD_UNCHANGED);
if (src->data == nullptr)
{
__android_log_print(ANDROID_LOG_VERBOSE, "NATIVE", "You reached nullptr");
return nullptr;
}
if (DEBUG_NATIVE)
__android_log_print(ANDROID_LOG_VERBOSE, "NATIVE", "convert_from_img_array_to_matrix() --- len before:%d len after:%d width:%d height:%d",
*imgLengthBytes, src->step[0] * src->rows,
src->cols, src->rows);
*imgLengthBytes = src->step[0] * src->rows;
return src;
}
Can someone suggest what am I doing wrong?
I am consuming a web service that return an XML of data, how can i convert a string containing lexical representation xsd:hexBinary not base64 format to Uint8List, coming from java i can do this by :
import javax.xml.bind.DatatypeConverter;
....
byte[] decoder = DatatypeConverter.parseHexBinary(hexStringXls);
or
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
Is this what you want?
final s = "somestring";
final List<int> bytes = s.codeUnits;
https://api.dart.dev/stable/2.8.4/dart-core/String/codeUnits.html
I need to encode and decode BER data. .NET has the class System.DirectoryServices.Protocols.BerConverter
The static method requires me to enter a string in the first parameter as shown below
byte[] oid = { 0x30, 0xD, 0x6, 0x9, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0xD, 0x1, 0x1, 0x1, 0x5, 0x0 }; // Object ID for RSA
var result2 = System.DirectoryServices.Protocols.BerConverter.Decoding("?what goes here?", oid);
BER encoding is used in LDAP, Certificates, and is commonplace in many other formats.
I'll be happy with information telling me how to Encode or Decode on this class. There is nothing on Stack Overflow or the first few pages of Google (or Bing) regarding this.
Question
How do I convert the byte array above to the corresponding OID using BER decoding?
How can I parse (or attempt to parse) SubjectPublicKeyInfo ASN.1 data in DER or BER format?
It seems the DER encoding\decoding classes are internal to the .NET framework. If so, where are they? (I'd like to ask connect.microsoft.com to make these members public)
How do I convert the byte array above to the corresponding OID using BER decoding?
After you have extracted the OID byte array, you can convert it to an OID string using OidByteArrayToString(). I have included the code below, since I couldn't find a similar function in the .NET libraries.
How can I parse (or attempt to parse) SubjectPublicKeyInfo ASN.1 data in DER or BER format?
I was not able to find a TLV parser in the .NET SDK either. Below is an implementation of a BER TLV parser, BerTlv. Since DER is a subset of BER, parsing will work the same way. Given a BER-TLV byte[] array, it will return a list of BerTlv objects that support access of sub TLVs.
It seems the DER encoding\decoding classes are internal to the .NET framework. If so, where are they? (I'd like to ask connect.microsoft.com to make these members public)
Maybe somebody else can answer this question.
Summary
Here is an example of how you can use the code provided below. I have used the public key data you provided in your previous post. The BerTlv should probably be augmented to support querying like BerTlv.getValue(rootTlvs, '/30/30/06');.
public static void Main(string[] args)
{
string pubkey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDrEee0Ri4Juz+QfiWYui/E9UGSXau/2P8LjnTD8V4Unn+2FAZVGE3kL23bzeoULYv4PeleB3gfmJiDJOKU3Ns5L4KJAUUHjFwDebt0NP+sBK0VKeTATL2Yr/S3bT/xhy+1xtj4RkdV7fVxTn56Lb4udUnwuxK4V5b5PdOKj/+XcwIDAQAB";
byte[] pubkeyByteArray = Convert.FromBase64String(pubkey);
List<BerTlv> rootTlvs = BerTlv.parseTlv(pubkeyByteArray);
BerTlv firstTlv = rootTlvs.Where(tlv => tlv.Tag == 0x30).First();//first sequence (tag 30)
BerTlv secondTlv = firstTlv.SubTlv.Where(tlv => tlv.Tag == 0x30).First();//second sequence (tag 30)
BerTlv oid = secondTlv.SubTlv.Where(tlv => tlv.Tag == 0x06).First();//OID tag (tag 30)
string strOid = OidByteArrayToString(oid.Value);
Console.WriteLine(strOid);
}
Output:
1.2.840.113549.1.1.1
OID Encode/Decode
public static byte[] OidStringToByteArray(string oid)
{
string[] split = oid.Split('.');
List<byte> retVal = new List<byte>();
//root arc
if (split.Length > 0)
retVal.Add((byte)(Convert.ToInt32(split[0])*40));
//first arc
if (split.Length > 1)
retVal[0] += Convert.ToByte(split[1]);
//subsequent arcs
for (int i = 2; i < split.Length; i++)
{
int arc_value = Convert.ToInt32(split[i]);
Stack<byte> bytes = new Stack<byte>();
while (arc_value != 0)
{
byte val = (byte) ((arc_value & 0x7F) | (bytes.Count == 0 ? 0x0:0x80));
arc_value >>= 7;
bytes.Push(val);
}
retVal.AddRange(bytes);
}
return retVal.ToArray();
}
public static string OidByteArrayToString(byte[] oid)
{
StringBuilder retVal = new StringBuilder();
//first byte
if (oid.Length > 0)
retVal.Append(String.Format("{0}.{1}", oid[0] / 40, oid[0] % 40));
// subsequent bytes
int current_arc = 0;
for (int i = 1; i < oid.Length; i++)
{
current_arc = (current_arc <<= 7) | oid[i] & 0x7F;
//check if last byte of arc value
if ((oid[i] & 0x80) == 0)
{
retVal.Append('.');
retVal.Append(Convert.ToString(current_arc));
current_arc = 0;
}
}
return retVal.ToString();
}
BER-TLV Parser
class BerTlv
{
private int tag;
private int length;
private int valueOffset;
private byte[] rawData;
private List<BerTlv> subTlv;
private BerTlv(int tag, int length, int valueOffset, byte[] rawData)
{
this.tag = tag;
this.length = length;
this.valueOffset = valueOffset;
this.rawData = rawData;
this.subTlv = new List<BerTlv>();
}
public int Tag
{
get { return tag; }
}
public byte[] RawData
{
get { return rawData; }
}
public byte[] Value
{
get
{
byte[] result = new byte[length];
Array.Copy(rawData, valueOffset, result, 0, length);
return result;
}
}
public List<BerTlv> SubTlv
{
get { return subTlv; }
}
public static List<BerTlv> parseTlv(byte[] rawTlv)
{
List<BerTlv> result = new List<BerTlv>();
parseTlv(rawTlv, result);
return result;
}
private static void parseTlv(byte[] rawTlv, List<BerTlv> result)
{
for (int i = 0, start=0; i < rawTlv.Length; start=i)
{
//parse Tag
bool constructed_tlv = (rawTlv[i] & 0x20) != 0;
bool more_bytes = (rawTlv[i] & 0x1F) == 0x1F;
while (more_bytes && (rawTlv[++i] & 0x80) != 0) ;
i++;
int tag = Util.getInt(rawTlv, start, i-start);
//parse Length
bool multiByte_Length = (rawTlv[i] & 0x80) != 0;
int length = multiByte_Length ? Util.getInt(rawTlv, i+1, rawTlv[i] & 0x1F) : rawTlv[i];
i = multiByte_Length ? i + (rawTlv[i] & 0x1F) + 1: i + 1;
i += length;
byte[] rawData = new byte[i - start];
Array.Copy(rawTlv, start, rawData, 0, i - start);
BerTlv tlv = new BerTlv(tag, length, i - length, rawData);
result.Add(tlv);
if (constructed_tlv)
parseTlv(tlv.Value, tlv.subTlv);
}
}
}
Here is a utility class that contains some functions used in the class above. It is included for the sake of clarity how it works.
class Util
{
public static string getHexString(byte[] arr)
{
StringBuilder sb = new StringBuilder(arr.Length * 2);
foreach (byte b in arr)
{
sb.AppendFormat("{0:X2}", b);
}
return sb.ToString();
}
public static byte[] getBytes(String str)
{
byte[] result = new byte[str.Length >> 1];
for (int i = 0; i < result.Length; i++)
{
result[i] = (byte)Convert.ToInt32(str.Substring(i * 2, 2), 16);
}
return result;
}
public static int getInt(byte[] data, int offset, int length)
{
int result = 0;
for (int i = 0; i < length; i++)
{
result = (result << 8) | data[offset + i];
}
return result;
}
}
I have problem converting .NET C# AES 128 Encryption to iOS (iPhone). Everything generated correctly except the last block. The final call to xfrm.TransformFinalBlock generate differently than what I got from iOS code (using CCCryptorFinal). I am using the same parameter for BlockSize, Key and IV. What else am I missing? Thank you.
Obj-C
CCCryptorStatus ccStatus = kCCSuccess;
CCCryptorRef thisEncipher = NULL;
// Create and Initialize the crypto reference.
ccStatus = CCCryptorCreate(kCCEncrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
szKey,
kCCKeySizeAES128,
iv,
&thisEncipher
);
// Calculate byte block alignment for all calls through to and including final.
int bufferPtrSize = CCCryptorGetOutputLength(thisEncipher, InputLength, true);
unsigned char *szResult = (unsigned char *)malloc(bufferPtrSize+1);
memset(szResult, 0x00, bufferPtrSize+1);
while (dataEncrypted < dataToEncrypt)
{
bool final = (dataToEncrypt - dataEncrypted) <= lrcEncryptionBlockSize;
if (final)
{
// Finalize everything to the output buffer.
ccStatus = CCCryptorFinal(thisEncipher,
szResult + dataEncrypted,
bufferPtrSize - dataEncrypted,
pOutSize
);
dataEncrypted += *pOutSize;
for(int c=0;c<dataEncrypted;++c)
{
printf("\n%d => %d\n", c, szResult[c]);
}
success = true;
break;
}
else
{
// Actually perform the encryption or decryption.
ccStatus = CCCryptorUpdate( thisEncipher,
szInput+cb,
lrcEncryptionBlockSize,
szResult+dataEncrypted,
bufferPtrSize - dataEncrypted,
pOutSize
);
dataEncrypted += *pOutSize;
cb += lrcEncryptionBlockSize;
}
}
if (thisEncipher) {
(void) CCCryptorRelease(thisEncipher);
thisEncipher = NULL;
}
C#
AesManaged aesAlg = new AesManaged();
ICryptoTransform xfrm;
aesAlg.IV = GenerateIV();
aesAlg.Key = "1111111111111111";
aesAlg.BlockSize = 128;
xfrm = aesAlg.CreateEncryptor();
while (dataEncrypted < dataToEncrypt)
{
bool final = (dataToEncrypt - dataEncrypted) <= lrcEncryptionBlockSize;
int nbytes = !final ? lrcEncryptionBlockSize : (int)(dataToEncrypt - dataEncrypted);
if (final)
{
byte[] finalblock = xfrm.TransformFinalBlock(message, cb, nbytes);
Buffer.BlockCopy(finalblock, 0, message, cb, lrcEncryptionBlockSize);
success = true;
break;
}
else
{
dataEncrypted += (uint)xfrm.TransformBlock(message, cb, nbytes, message, cb);
cb += lrcEncryptionBlockSize;
}
}
xfrm.Dispose();
aesAlg.Clear();
If only the last block differs, the difference is probably that they use different padding. The first example uses PKCS7, but I cant see what the second one uses.