When calling the .toBuffer() method on a sharp object, I get the following error:
Input buffer contains unsupported image format
I'm fetching an image from S3, and I am certain its retrieved as a Buffer which is then passed to sharp.
Moreover, when I console.log the base64 of the buffer and check what's behind, I do get the original image and the filetype is jpeg, so I can't seem to figure out why it would say that the Input buffer contains unsupported image format.
const imageBuffer = fileFromS3.Body
console.log(imageBuffer)
console.log(imageBuffer.toString('base64'))
let result = await sharp(imageBuffer)
.toColourspace('b-w')
.sharpen()
.toBuffer()
When I check the sharp object before running toBuffer() I get this data in the object:
let result = await sharp(imageBuffer)
.toColourspace('b-w')
.sharpen()
console.log(result)
Prints:
...
input: {
failOnError: true,
limitInputPixels: 268402689,
sequentialRead: false,
buffer: <Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01 00 01 00 00 ff db 00 43 00 03 02 02 02 02 02 03 02 02 02 03 03 03 03 04 06 04 04 04 04 04 08 06 06 05 ... 96981 more bytes>
}
lakhal#lakhal-ThinkPad-T430s:~$ hexdump -C /dev/bus/usb/003/014
00000000 12 01 00 02 e0 00 00 40 e8 04 63 68 ff ff 02 03 |.......#..ch....|
00000010 04 01 09 02 4b 00 02 01 00 c0 30 08 0b 00 02 e0 |....K.....0.....|
00000020 01 03 07 09 04 00 00 01 e0 01 03 05 05 24 00 10 |.............$..|
00000030 01 05 24 01 00 01 04 24 02 00 05 24 06 00 01 07 |..$....$...$....|
00000040 05 83 03 08 00 09 09 04 01 00 02 0a 00 00 06 07 |................|
00000050 05 81 02 00 02 00 07 05 02 02 00 02 00 |.............|
0000005d
The file allows you to read certain USB descriptors from the device. The USB device descriptor, which is defined by the USB specification, is located at the beginning of the file.
For more details, see the file usb/core/devio.c in the source code of your kernel. In particular, look at the function usbdev_read, which implements the kernel side of the read system call for these special files. I cannot find official documentation at the moment.
I believe some parts of the file are "holes", meaning that you won't be able to read any data from them, and you might get meaningless data depending on whether the program you uses initializes the buffers it uses for reading from the file.
I wrote the below program to generate random numbers of different lengths, using two different algorithms (ALG_SECURE_RANDOM and ALG_PSEUDO_RANDOM).
P1 and P2 in the APDU command specify the algorithm and the random length in order.
P1 = 0X01 : ALG_SECURE_RANDOM
P1 = 0X02 : ALG_PSEUDO_RANDOM
P2 = Random number length
public class RandGen extends Applet {
byte[] generatedArray;
byte[] generatedRandom;
RandomData randomDataSecure = RandomData
.getInstance(RandomData.ALG_SECURE_RANDOM);
RandomData randomDataPseudo = RandomData
.getInstance(RandomData.ALG_PSEUDO_RANDOM);
private RandGen() {
}
public static void install(byte bArray[], short bOffset, byte bLength)
throws ISOException {
new RandGen().register();
}
public void process(APDU apdu) throws ISOException {
if (selectingApplet()) {
return;
}
byte[] buffer = apdu.getBuffer();
generatedArray = JCSystem.makeTransientByteArray(
(short) buffer[ISO7816.OFFSET_P2], JCSystem.CLEAR_ON_DESELECT);
switch (buffer[ISO7816.OFFSET_P1]) {
case (0x01):
generatedRandom = secureRandomGenerator(apdu);
break;
case (0x02):
generatedRandom = pseudoRandomGenerator(apdu);
break;
default:
return;
}
Util.arrayCopyNonAtomic(generatedRandom, (short) 0, buffer, (short) 0,
(short) ISO7816.OFFSET_P2);
apdu.setOutgoingAndSend((short) 0, (short) ISO7816.OFFSET_P2);
}
public byte[] secureRandomGenerator(APDU apdu) {
byte[] buffer = apdu.getBuffer();
randomDataSecure.generateData(generatedArray, (short) 0,
(short) buffer[ISO7816.OFFSET_P2]);
return generatedArray;
}
public byte[] pseudoRandomGenerator(APDU apdu) {
byte[] buffer = apdu.getBuffer();
randomDataPseudo.generateData(generatedArray, (short) 0,
(short) buffer[ISO7816.OFFSET_P2]);
return generatedArray;
}
}
The CAP file generated and uploaded on the card successfully, but when I send APDU commands to the card, I receive the 0X6F00 status word :
OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000202
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 02 02
Received (SW1=0x90, SW2=0x00)
OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000102
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 01 02
Received (SW1=0x6F, SW2=0x00)
Is there something wrong in my applet?
Update:
Based on dear #Vojta's answer, I replace
Util.arrayCopyNonAtomic(generatedRandom, (short) 0, buffer, (short) 0,
(short) ISO7816.OFFSET_P2);
apdu.setOutgoingAndSend((short) 0, (short) ISO7816.OFFSET_P2);
With following lines in process() method :
Util.arrayCopyNonAtomic(generatedRandom, (short) 0, buffer, (short) 0,
(short) buffer[ISO7816.OFFSET_P2]);
apdu.setOutgoingAndSend((short) 0, (short) buffer[ISO7816.OFFSET_P2]);
Now I have a weird output in OpenSC-Tool output :
Secure random generator :
OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000110
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 01 10
Received (SW1=0x90, SW2=0x00):
B8 1F 80 25 A2 8E 25 30 F8 22 F8 40 0F AE B0 6C ...%..%0.".#...l
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 .....
OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000110
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 01 10
Received (SW1=0x6F, SW2=0x00)
OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000110
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 01 10
Received (SW1=0x90, SW2=0x00):
F6 45 A9 0C 0C 3B 3A 5A 5F DC A8 36 .E...;:Z_..6
Pseudo random generator :
OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000210
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 02 10
Received (SW1=0x90, SW2=0x00):
37 FD FC 67 EB 9E 21 00 6B E9 44 A7 21 3F 31 9A 7..g..!.k.D.!?1.
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 .......
OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000210
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 02 10
Received (SW1=0x6F, SW2=0x00)
OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000210
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 02 10
Received (SW1=0x90, SW2=0x00):
72 FE 48 1B 9A A0 BD 2D DF F9 E7 F8 58 CF B7 C0 r.H....-....X...
00 00 00 00 00 00 00 00 00 00 00 ...........
Why I have different output for a single command?
There is a little bug in your code. You want
Util.arrayCopyNonAtomic(generatedRandom, (short) 0, buffer, (short) 0,
(short) buffer[ISO7816.OFFSET_P2]);
instead of
Util.arrayCopyNonAtomic(generatedRandom, (short) 0, buffer, (short) 0,
(short) ISO7816.OFFSET_P2);
General rule: ALWAYS surround the content of your process method with a try-catch block and set status words according to the type and reason of the exception. Otherwise you get only 6F00 and you do not know what really happened. If you followed this rule, you would know that ArrayIndexOutOfBoundsException was thrown.
Answer to update:
Weird output is caused by the fact, that
Util.arrayCopyNonAtomic(generatedRandom, (short) 0, buffer, (short) 0,
(short) buffer[ISO7816.OFFSET_P2]);
apdu.setOutgoingAndSend((short) 0, (short) buffer[ISO7816.OFFSET_P2]);
overwrites the buffer[ISO7816.OFFSET_P2] with some random value and then this value is used on the next line. You should store buffer[ISO7816.OFFSET_P2] in RAM in the beginning of the process method:
final byte p2 = buffer[ISO7816.OFFSET_P2];
Answer to comment below:
You have troubles for P2 >= 0x80, because of casting byte to short. Unfortunately, JavaCard handles byte as signed, that is why your length for P2 >= 0x80 is negative. You could easily avoid this by:
final short outputLen = (short) (buffer[ISO7816.OFFSET_P2] & 0xFF);
command not supported
You have the wrong instruction joining together.
I am running this (http://www.linux-usb.org/gadget/usb.c) Gadget FS user mode driver on an embedded device.
When I connect it to Windows, these are the GET_DESCRIPTOR setup requests I receive:
80 06 03 03 09 04 ff 00
80 06 00 03 00 00 ff 00
80 06 02 03 09 04 ff 00
80 06 03 03 09 04 ff 00
80 06 00 03 00 00 ff 00
80 06 02 03 09 04 ff 00
`bmRequestType`: 0x80 Device-to-host transfer direction
`bRequest`: 0x06 GET_DESCRIPTOR
`wValueH` : 0x03 Descriptor Type 'String'
`wValueL` : Descriptor Index
`wIndex` : 0x04 0x09 Language ID "US-English" for Descriptor Types "String", 0x00 for others
`wLength` : Length of the requested descriptor
These are the setup requests coming from the Linux host when i connect the device.
80 06 00 03 00 00 ff 00
80 06 02 03 09 04 ff 00
80 06 01 03 09 04 ff 00
80 06 03 03 09 04 ff 00
80 06 ee 03 00 00 00 04
The last one makes my GadgetFS implementation STALL. The Descriptor Type is 3, meaning a Descriptor of type "String" is requested but in wIndex no Language ID is provided (0x00 0x00). Also, the Descriptor Index is 0xEE, but why would you have 238 String Descriptors for a device?
Notice also the length of the requested descriptor: 0x0400 (1024).
This is a code excerpt from the driver implementation I use (linux-usb.org) that handles the setup requests:
case USB_REQ_GET_DESCRIPTOR: //0x06
if (setup->bRequestType != USB_DIR_IN) //USB_DIR_IN = 0x80
goto stall;
switch (value >> 8) // wValueH: Descriptor Type
{
case USB_DT_STRING: // 0x03 Type = "String"
{
tmp = value & 0x0ff; // wValueL : Descriptor Index
struct usb_gadget_strings strings = {
0x0409, /* "en-us" */
m_aUsbStringtab
};
index = 0x0409
if (tmp != 0 && index != strings.language) //This makes it STALL when connected to a linux
goto stall;
I'd really appreciate it, if someone could help me!
So appearently on linux, the setup request with a descriptor index of 0xEE and a length of 1024 is not sent by libusb on linux but by mtp-probe (part of libmtp, media transfer protocol).
I use node-canvas;
....
var content = canvas.toBuffer();
var length=content.length;
console.log(content);
result:
<SlowBuffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00 30 00 00 00 30 08 06 00 00 00 57 02 f9 87 00 00 00 06 62 4b 47 44 00 ff 00 ff 00 ff a0 bd a7 93 ...>
And
var buf=new SlowBuffer(length);
buf.write(content.toString());
console.log(buf);
result:
<Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 01 00 28 00 28 00 00 ff db 00 43 00 08 06 06 07 06 05 08 07 07 07 09 09 08 0a 0c 14 0d 0c 0b 0b 0c 19 12 13 0f 14 ...>
They are not equal:( ,so when I store it into redis ,I can't get it back;
Depending on the format you want, you can use the following methods:
buf.toJSON() // Straight to JSON format
buf.toString('utf8') ; // UTF8 format
Read on for more alternatives: https://nodejs.org/api/buffer.html#buffer_buf_tostring_encoding_start_end
You can't just call Buffer.toString and assume that everything will be all right, since the default encoding is utf8. If you want to encode binary data, you need base64 encoding.