I am building an inhouse Invoicing solution for my company. The government requires us to create QR Code fields encoded in Tag-Length-Value (TLV) format.
The TLV encoding shall be as follows:
Tag: the tag value as mentioned above stored in one byte
Length: the length of the byte array resulted from the UTF8 encoding of the field value. The length shall be stored in one byte.
Value: the byte array resulting from the UTF8 encoding of the field value.
In the example they have provided this Base64 Output
AQkxMjM0NTY3ODkCCjEyLzEyLzIwMjADBDEwMDADAzE1MPaIn2Z2jg6VqWvWV6IrZZNzLF7xvZrWXW5xRV5yFY2xFu0ycXOiyqV0k7Wsh6b1IcE2Tfzap1AQAQVsktmsv1FFQ1MxIAAAAGKblFMh9nFRSn8tvftXqo9zRSz2VEAPITSZ3W7UDHKhUx+7yXGijLtJSZGXMOc+jpKwARzDl68GmmRd75NWdOs=
When I decode using
$base64 = "AQkxMjM0NTY3ODkCCjEyLzEyLzIwMjADBDEwMDADAzE1MPaIn2Z2jg6VqWvWV6IrZZNzLF7xvZrWXW5xRV5yFY2xFu0ycXOiyqV0k7Wsh6b1IcE2Tfzap1AQAQVsktmsv1FFQ1MxIAAAAGKblFMh9nFRSn8tvftXqo9zRSz2VEAPITSZ3W7UDHKhUx+7yXGijLtJSZGXMOc+jpKwARzDl68GmmRd75NWdOs=";
echo base64_decode($base64);
The response i get is:
123456789
12/12/20201000150���fv���k�W�+e�s,^��]nqE^r���2qs�ʥt������!�6M�ڧPl�٬�QECS1 b��S!�qQJ-��W��sE,�T#!4��n�r�S��q���II��0�>���×��d]�Vt�
Tag 1: Seller's Name
Tag 2: Vat Registration number
Tag 3: Timestamp of the invoice
Tag 4: Invoice Total
Tag 5: Tax Total
Tag 6: Hash of XML invoice
Tag 7: ECDSA Signature
Tag 8: ECDSA Public Key
Tag 9: ECDSA signature of the cryptographic stamp’s public key
What Am I doing wrong here and what is the right syntax to correct it?
Knowing it's binary data, we can echo it with bin2hex(base64_decode($base64)), and see this:
0109313233343536373839020a31322f31322f323032300304313030300303313530f6889f66768e0e95a96bd657a22b6593732c5ef1bd9ad65d6e71455e72158db116ed327173a2caa57493b5ac87a6f521c1364dfcdaa7501001056c92d9acbf514543533120000000629b945321f671514a7f2dbdfb57aa8f73452cf654400f213499dd6ed40c72a1531fbbc971a28cbb4949919730e73e8e92b0011cc397af069a645def935674eb
For easier viewing, I used the command line tools base64 -d and xxd to get this view:
00000000: 0109 3132 3334 3536 3738 3902 0a31 322f ..123456789..12/
00000010: 3132 2f32 3032 3003 0431 3030 3003 0331 12/2020..1000..1
00000020: 3530 f688 9f66 768e 0e95 a96b d657 a22b 50...fv....k.W.+
00000030: 6593 732c 5ef1 bd9a d65d 6e71 455e 7215 e.s,^....]nqE^r.
00000040: 8db1 16ed 3271 73a2 caa5 7493 b5ac 87a6 ....2qs...t.....
00000050: f521 c136 4dfc daa7 5010 0105 6c92 d9ac .!.6M...P...l...
00000060: bf51 4543 5331 2000 0000 629b 9453 21f6 .QECS1 ...b..S!.
00000070: 7151 4a7f 2dbd fb57 aa8f 7345 2cf6 5440 qQJ.-..W..sE,.T#
00000080: 0f21 3499 dd6e d40c 72a1 531f bbc9 71a2 .!4..n..r.S...q.
00000090: 8cbb 4949 9197 30e7 3e8e 92b0 011c c397 ..II..0.>.......
000000a0: af06 9a64 5def 9356 74eb ...d]..Vt.
You haven't explained what the possible "tag" values are, but I can see the start of that string has a tag of 0x01, a length of 0x09, and the following 9 bytes are ASCII/UTF-8 for 123456789; it then has a tag of 0x02, a length of 0x0a, and the next 10 characters are ASCII/UTF-8 12/12/2020; and so on.
Later, there is a tag of f6 with a length of 88, and some binary data, but without knowing what tag f6 means, I've no reason to suppose that's a problem - maybe it embeds an image, or a stream of compressed data.
For Decode QR Code (Zatca) in PHP
Read QR Code - example base64 code.
Decode the base64 code.
use preg_replace to remove unicode values from the string
And explode to get array
Sample code
$base64 = "AQZSYWZlZXECDTEyMzQ1Njc4OVQxMjUDFDIwMjEtMDctMTJUMTQ6MjU6MDlaBAM3ODYFAjI1";
$decoded = base64_decode($base64);
//print_r($decoded)
//raw data
//\u0001\u0006Rafeeq\u0002\t123456789\u0003\u00142021-07-12T14:25:09Z\u0004\u0003786\u0005\u000225
$result_data = preg_replace('/[\x00-\x1F\x80-\xFF]/', ',', $decoded);
$actula_data = explode(',,', $result_data);
print_r($actula_data);
Output :
["","Rafeeq","123456789T125","2021-07-12T14:25:09Z","786","25"]
Edited:
In the Security Specification it says:
4.2 Structure of the Cryptographic Stamp applied on the QR code
The below specifications of the Cryptographic Stamp required for the QR code are based Annex (2) of the Controls, Requirements, Technical Specifications and
Procedural Rules for Implementing the Provisions of the E-Invoicing Regulation.
The QR code Cryptographic Stamp shall be generated use the same digital certificate used for stamping the electronic invoices. Please refer to section 3 for the
requirements applicable to the management and use of digital certificates used to apply Cryptographic Stamp on electronic invoices.
The Cryptographic Stamp shall be applied on the entire TLV encoding of the QR code fields (from tag 1 to tag 6) then it shall be appended to the TLV structure. The
Cryptographic Stamp consists of two fields as shown in the below table:
I assume the part of the data is a part of the Cryptographic Stamp
Related
I need to be able to convert any string into a code128 barcode that can be printed on a PDF.
My idea was to embed a code128 font into the PDF and simply use that font to render the string that I need to show as a barcode, letter for letter.
However, I found out that I also need to calculate a checksum and include the start and stop characters.
Is this not possible using PHP? I have not found any solution anywhere. The only solutions that I could find are for directly rendering the barcode as an image, which does not help in my current situation, since I need to use a font to create the barcode in the PDF.
If you restrict your efforts to 128B, you have access to upper and lower case characters, numbers and most punctuation. It also saves you from having to write code to shift in and out of A and C symbologies. This makes the code to calculate the checksum really trivial.
Code 128B start character has a value of 104. The stop character for all Code 128 variations has a value of 106, but that value does not figure into the chksum calculation. Let's pick the string "Hello" for a real life exercise. You'll want to make sure you have access to the Code 128 table. All the values I will be discussing are out of that table and not ASCII or UTF-8.
The checksum is calculated by adding the multiple of a character’s value by its position in the barcode with the exception of the start code.
While the start code’s position is ‘1’, so is the position of the first character following the start code. So the start code and the first byte of data (‘H’) are both multiplied by the number 1 ((104 × 1) + (40 × 1) = 144).
The following 4 bytes get an incrementally higher multiplier ((69 x 2) + (76 × 3) + (76 × 4) + (79 × 5) = 1065). Summing it all up together (144 + 1065) we get 1209.
You should be able to use the modulus operator (1209 % 103) in PHP to get 76 for the checksum character for the Code 128B string “Hello” (the 103 is a constant, trust me on that). So the final array of codes to map "Hello" into a Code 128 barcode is:
[104 40 69 76 76 79 76 106].
You'll need lookup tables to convert the string character values to Code 128B character values to whatever your barcode font is expecting. But all you need is a loop, an array index, an accumulator for the sum of the factors and a modulus operator against the constant value of 103.
The easisest way to generate a barcode in PHP for PDF is to use a dedicated software library.
AFAIK, the most complete one is currently the tc-lib-barcode (https://github.com/tecnickcom/tc-lib-barcode) that allows you to generate both linear and bidimensional barcodes. The included example should give you a quick start.
The source code is fully PSR-2 compliant and can be easily added to your PHP projects using Composer.
The original code has been ported and refactored from TCPDF and already used in billions of documents.
i am working on a php-script which encodes given text and hides that in an Image using LSB. But the encoded text is a Byte Array (text encrypted using mcrypt with rijndael-256 and then unpacked with unpack("C*", $encryptedText);) i have tp add the array-size at the beginning of the Array. if i would not do this, reading the Bytes from the Image again would be terrible later on, because the script would not know where to stop reading. I added size Information at the beginning of the Array using These lines of code:
$size = count($byteArray);
array_unshift($byteArray, $size >> 24, ($size & 0xff0000) >> 16, ($size & 0xff00) >> 8, $size & 0xff);
so the size is added in integer Format (4bytes), but now every Image created would have the characteristics that the first hidden Bytes start mostly with Zeros, besause $size is mostly in the range of 60000 or lower. is there any way i can encode size or Change other parts of the program so that it works and the beginning of the bytearry is not nearly the same every time?
Instead of always having the first 4 bytes encoding how long your message is, you can use the last two bits from the first byte to encode how many bytes you need to read for $size. Say, 00 = 1, 01 = 2, 10 = 3 and 11 = 4. For example, if $size is small enough to be expressed with just two bytes, the first few bytes will read as follow:
First byte: xxxxxx01
Second and third bytes: $size
Fourth byte and onward: ByteArray...
You can spice things up further by using a randomised embedding method. You can use a pseudorandom number generator, or chaotic maps, such as the Logistic Map, or Tent Map. The seed or initial condition parameters will be required by the receipt to decipher in what order to read the bytes to extract the message. For example, consider 5 bytes to embed data and 5 numbers generated between 0 and 1.
(0.2843, 0.5643, 0.0904, 0.4308, 0.9866)
Sorting the numbers in ascending order gives you the following order, which you can use to embed your secret:
(3, 1, 4, 2, 5)
How would i check that a file is either jpeg, pdf or tiff? And I mean actually checking, not just from mime type and file extension.
I have access to the raw file data (this check is part of an uploader) and i need to verify that the files are either jpeg, pdf or tiff. I assume I would have to check for some sort of headers in the files but I have no idea what to look for and where to start.
Exif_imagetype is very useful for this: http://us2.php.net/manual/en/function.exif-imagetype.php
It scans the initial bytes of the file to determine the graphic type. It supports a large number of graphic formats (and returns false if it doesn't recognize the format).
You need to implement byte sequence tests.
Here is a guide to checking byte sequences for the most common image formats.
This can be tricky since all files must follow a certain kind of ISO standard with the "magical number" present, which basically is a "header" for the format.
I found this wiki-page about different signatures: http://en.wikipedia.org/wiki/List_of_file_signatures
So in the best case scenario you just need to validate these first bytes.
If you have access to the raw file, you can check the file header for its magic number. This number define the type of file.
to check for image types you can use the exif_imagetype function.
for pdf: you have to open the file and read the first bytes and look if it starts with '%PDF'
$fp = fopen($pdf, 'r');
if(fgets($fp, 4) == '%PDF')
{
... is pdf
}
fclose($fp);
There is no sure fired way to be certain but the first few binary bits of a file are its signature/fingerprint for the file handlers to test. see https://en.wikipedia.org/wiki/List_of_file_signatures
Every file type can vary considerably and some allow for variable / shifting headers, but with a degree of uncertainty (At one time PDF did not mandate the 40 bit signature to be first) we can assume the following hex values sometimes erroneously called "Magic Numbers" as representing the start of each bit stream.
So in general to answer the requested types
FF D8 (ÿØ) would be a Jpeg (EXCEPT JP2000=FF 4F or 00 00) in raw binary or /9j/4 in Base64 format
25 50 44 46 2d (%PDF-) would be the 40 bit signature of a PDF or JVBER in Base64 format
89 50 4E 47 (‰PNG) would be PNG in raw binary or iVBOR in Base64 format
just for good measure here is related older GIF sequence
47 49 46 38 (GIF8) and that's R0lGO as Base64 also we can see the first 8 bits are 01000111 for G
Thus in ALL the above cases just the first "8 bit / byte" would be a very good indicator, no need for Magic strings, but with Zip/###X such as docX pptX cbzX xlsX they ALL have the same Magic Number
50 4B (PK) base64 = UEsDB
Finally the last requested above was Tif(f) which can be two types, Intel or Motorola thus you need to test for
49 49 2A 00 (II* ) base64 = SUkqA
4D 4D 00 2A (MM *) base64 = TU0AK
I am parsing a XML file supplied by some software. Part of the parsing is extracting colors from some attributes. The problem I have is the color is a 12digit hex value. ie,
<Text AdornmentStyle="0" Background="#FFFFFFFFFFFF" Color="#DD6B08C206A2" Font="Courier Final Draft" RevisionID="0" Size="12" Style="">Test</Text>
As you can see the colors are 12digits long. I need to get the 6 digit color so I can display it correctly on html.
Has anyone come across this before?
Hope you can advise.
Never seen a 12-digit hex color string before. Must be using 2-bytes per channel, which means if you convert it, you're going to lose a bit of information.
I believe the color is in the format #RRRRGGGGBBBB, so take each 4 hexgits and divide by (16^4/16^2)=256, and round if necessary. That should do it.
...and if that doesn't give you the right color, try CMYK like cypher suggests: #CCCMMMYYYKKK (12-bits per channel).
e.g., to convert DD6B08C206A2 do:
0xDD6B / 0x100 = 0xDD
0x08C2 / 0x100 = 0x08
0x06A2 / 0x100 = 0x06
Put those back together and you get #DD0806.
I have just bought a GPS Tracker, it can send SMS to cellphone just fine. It also supports reporting to a server via GPRS.
I have setup the device to contact my own server on port 8123, it's a FreeBSD server and i have checked that i recieve packets on that port.
I successfully have setup a listener server written in PHP, and i can receive data from the device. But how do i convert the partial HEX data to something usefull (ASCII)?
Example data string:
$$^#T^#E Y'^WÿU210104.000,A,5534.4079,N,01146.2510,E,0.00,,170411,,*10|1.0|72|0000á
Unfortunately i don't know how i can copy-paste the HEX parts
Now how do i get the ID part out? I have tried echo hexdec(mb_substr($data, 4, 7));
The data is following this protocol
From the document:
Command format of GPRS packets are as follows:
From server to tracker:
##\r\n
From tracker to server:
$$\r\n
Note:
Do NOT input ‘’ when writing a command.
All multi-byte data complies with the following sequence: High byte prior to low byte.
The size of a GPRS packet (including data) is about 100 bytes
Item Specification
## 2 bytes. It means the header of packet from server to tracker.
It is in ASCII code (Hex code: 0x40)
$$ 2 bytes. It is the header of packet from tracker to server.
It is in ASCII code (Hex code: 0x24)
L 2 bytes. It means the length of the whole packet including
the header and ending character and it is in hex code
ID 7 bytes, ID must be digit and not over 14 digits, the unused byte
will be stuffed by ‘f’ or ‘0xff’. It is in the format of hex code.
For example, if ID is 13612345678, then it will be shown as
follows: 0x13, 0x61, 0x23, 0x45, 0x67, 0x8f, 0xff.
If all 7 bytes are 0xff, it is a broadcasting command. ID is in hex code
command 2 bytes. The command code is in hex code. Please refer to the
command list below.
data Min 0 byte and max 100 bytes. See Annex 1 for description of ‘data’.
checksum 2 bytes. It indicates CRC-CCITT (default is 0xffff) checksum of
all data (not including CRC itself and the ending character).
It is in hex code.
For example: 24 24 00 11 13 61 23 45 67 8f ff 50 00 05 d8 0d 0a
0x05d8 = CRC-CCITT (24 24 00 11 13 61 23 45 67 8f ff 50 00)
\r\n 2 bytes. It is the ending character and in hex code
(0x0d,0x0a in hex code)
Update
With the answer from Anomie, i was able to piece this together
$arr = unpack('H4length/H14id/H4cmd/H4crc/H4end', mb_substr($data, 2, 11) . mb_substr($data, -4));
var_dump($arr);
This will out put something like
array(5) {
["length"]=>
string(4) "0054"
["id"]=>
string(14) "004512345678ff"
["cmd"]=>
string(4) "9955"
["crc"]=>
string(4) "c97e"
["end"]=>
string(4) "0d0a"
}
It sounds like you are needing to convert binary data to integers or strings. The most straightforward way is to use unpack.
For example, to extract the length you already know you can use
$length_bin = substr($string, 2, 2);
To convert it to an integer, you can use something like
$length = unpack('v', $length_bin); $length = $length[1];
The 'v' code will work for the length and the checksum; if you have a number stored as 4 bytes use 'V', and for the ID you can use 'H*' to get it as a string of hex digits. Other codes are listed in the documentation.
A somewhat less straightforward way is to do the bit manipulation manually, after using unpack with C* to get an array of all the byte values. For example,
$bytes = unpack('C*', $length_bin);
$length = ($bytes[0] << 8) | $bytes[1];
You need to know the format of the messages you are going to receive from the device. You can get this info from the manufacturer. Then, depending on that, you have to create a proper listener in the server side.
I've been working with several devices like that and normally you have to create a process in the server listening to the port with a Socket (or similar). You may have an authentication process also to differentiate between devices (you can have more than one). After that, you simply get the data from the device, you parse it and you store it. Depending on the device you can also send requests or configurations.
Hope this helps
*Edit 26 April:* I have changed the question a bit, thus this seems out of place. Initial question was more on how to read the data from TCP.
I found some great articles on writing a TCP/socket server in PHP (/me slaps PHP around a bit with a large trout)
http://devzone.zend.com/article/1086
http://kevin.vanzonneveld.net/techblog/article/create_daemons_in_php/
Can't wait to get this going :)