I'm creating a low level HTTP server and I want to validate that my responses are correct.
Some of them are fine, but others fail. I have saved some responses as bytes and viewing them in HxD, and they look correct, but they obviously aren't in some way.
Here's the start of one HTTP response formatted as hex:
48 54 54 50 2F 31 2E 31 20 32 30 30 20 4F 4B 0D 0A 43 4F 4E 54 45 4E
54 2D 54 59 50 45 3A 20 69 6D 61 67 65 2F 70 6E 67 0D 0A 4C 41 53 54
2D 4D 4F 44 49 46 49 45 44 3A 20 53 75 6E 2C 20 30 31 20 4D 61 79 20
32 30 32 32 20 32 32 3A 32 34 3A 32 34 20 47 4D 54 0D 0A 41 43 43 45
50 54 2D 52 41 4E 47 45 53 3A 20 62 79 74 65 73 0D 0A 45 54 41 47 3A
20 22 37 35 37 35 35 33 36 61 61 35 64 64 38 31 3A 30 22 0D 0A 53 45
52 56 45 52 3A 20 4D 69 63 72 6F 73 6F 66 74 2D 49 49 53 2F 31 30 2E
30 0D 0A 58 2D 50 4F 57 45 52 45 44 2D 42 59 3A 20 41 53 50 2E 4E 45
54 0D 0A 44 41 54 45 3A 20 57 65 64 2C 20 30 34 20 4D 61 79 20 32 30
32 32 20 30 39 3A 30 31 3A 34 38 20 47 4D 54 0D 0A 43 4F 4E 54 45 4E
54 2D 4C 45 4E 47 54 48 3A 20 39 38 37 35 37 0D 0A 43 6F 6E 6E 65 63
74 69 6F 6E 3A 20 63 6C 6F 73 65 0D 0A 0D 0A 0D 0A 89 50 4E 47
How can I validate that the response I'm creating is valid according to RFC 2616?
I'm working in .NET but I don't mind if it's an online tool or a different platform.
Edit:
I've solved my issue with this particular example (3 crlfs instead of 2 between head and body) but I'd still like to know how I can validate these requests automatically.
I ended up achieving this with this nuget package and the following code:
if (System.Diagnostics.Debugger.IsAttached)
{
using (var handler = new HttpParserDelegate())
using (var parser = new HttpCombinedParser(handler))
{
parser.Execute(arr);
}
if (!handler.HttpRequestResponse.IsEndOfMessage)
{
System.Diagnostics.Debugger.Break();
throw new InvalidOperationException($"An HTTP response was serialized but it is not a valid response");
}
}
I have this string:
x <- "W3siY29kZSI6IkIxMTgyIiwiZGVzY3JpcHRpb24iOiJUaXJlIHByZXNzdXJlIG1vbml0b3IgbW9kdWxlIiwiZmF1bHRJbmZvcm1hdGlvbnMiOlt7ImRlc2NyaXB0aW9uIjoiLS0tIn0seyJkZXNjcmlwdGlvbiI6IlRSVUUiLCJkZXNjcmlwdGlvbl9lbmciOiJUUlVFIiwiZGVzY3JpcHRpb25fZnJlIjoiVFJVRSIsImRlc2NyaXB0aW9uX2dlciI6IlRSVUUiLCJkZXNjcmlwdGlvbl9zcGEiOiJUUlVFIiwiZGVzY3JpcHRpb25faXRhIjoiVFJVRSIsImRlc2NyaXB0aW9uX3R1ciI6IlRSVUUifV0sImZyZWV6ZUZyYW1lcyI6W10sImVuaGFuY2VkRHRjSW5mb3MiOltdLCJzdGF0dXMiOiJBQ1RJVkUiLCJzeXN0ZW0iOiJNVUxUSUZVTkNUSU9OIiwic3lzdGVtTWV0YSI6eyJzeXN0ZW1OYW1lIjpudWxsLCJzdWJTeXN0ZW1OYW1lIjpudWxsfSwiZGVzY3JpcHRpb25fZW5nIjoiVGlyZSBwcmVzc3VyZSBtb25pdG9yIG1vZHVsZSIsImRlc2NyaXB0aW9uX2ZyZSI6Ik1vZHVsZSBkZSBzdXJ2ZWlsbGFuY2UgZGUgbGEgcHJlc3Npb24gZGVzIHBuZXVzIiwiZGVzY3JpcHRpb25fZ2VyIjoiUmVpZmVuZHJ1Y2vDvGJlcndhY2h1bmciLCJkZXNjcmlwdGlvbl9zcGEiOiJNw7NkdWxvIGRlIGNvbnRyb2wgZGUgbGEgcHJlc2nDs24gZGUgbG9zIG5ldW3DoXRpY29zIiwiZGVzY3JpcHRpb25faXRhIjoiTW9kdWxvIG1vbml0b3IgZGkgcHJlc3Npb25lIHBuZXVtYXRpY28iLCJkZXNjcmlwdGlvbl90dXIiOiJMYXN0aWsgYmFzxLFuY8SxIGl6bGVtZSBtb2TDvGzDvCJ9LHsiY29kZSI6IkIxMjREIiwiZGVzY3JpcHRpb24iOiJTZW5zb3IsIHR5cmUgcHJlc3N1cmUiLCJmYXVsdEluZm9ybWF0aW9ucyI6W3siZGVzY3JpcHRpb24iOiItLS0ifSx7ImRlc2NyaXB0aW9uIjoiVFJVRSIsImRlc2NyaXB0aW9uX2VuZyI6IlRSVUUiLCJkZXNjcmlwdGlvbl9mcmUiOiJUUlVFIiwiZGVzY3JpcHRpb25fZ2VyIjoiVFJVRSIsImRlc2NyaXB0aW9uX3NwYSI6IlRSVUUiLCJkZXNjcmlwdGlvbl9pdGEiOiJUUlVFIiwiZGVzY3JpcHRpb25fdHVyIjoiVFJVRSJ9XSwiZnJlZXplRnJhbWVzIjpbXSwiZW5oYW5jZWREdGNJbmZvcyI6W10sInN0YXR1cyI6IkFDVElWRSIsInN5c3RlbSI6Ik1VTFRJRlVOQ1RJT04iLCJzeXN0ZW1NZXRhIjp7InN5c3RlbU5hbWUiOm51bGwsInN1YlN5c3RlbU5hbWUiOm51bGx9LCJkZXNjcmlwdGlvbl9lbmciOiJTZW5zb3IsIHR5cmUgcHJlc3N1cmUiLCJkZXNjcmlwdGlvbl9mcmUiOiJDYXB0ZXVyLCBwcmVzc2lvbiBkZXMgcG5ldXMiLCJkZXNjcmlwdGlvbl9nZXIiOiJTZW5zb3IgUmVpZmVuZHJ1Y2siLCJkZXNjcmlwdGlvbl9zcGEiOiJTZW5zb3IgZGUgcHJlc2nDs24gZGVsIG5ldW3DoXRpY28iLCJkZXNjcmlwdGlvbl9pdGEiOiJTZW5zb3JlLCBwcmVzc2lvbmUgcG5ldW1hdGljaSIsImRlc2NyaXB0aW9uX3R1ciI6IlNlbnPDtnIsIGxhc3RpayBoYXZhIGJhc8SxbmPEsSJ9XQ=="
I know it has been encoded using base64. Doing a quick search on internet, I found that in R there are some packages to encode/decode base64.
Package jsonlite with the function base64dec()
Package base64decode with the function base64decode().
In both cases, when running...
base64dec(x)
base64decode(x)
I get this result, which is a binary output:
[1] 5b 7b 22 63 6f 64 65 22 3a 22 42 31 31 38 32 22 2c 22 64 65 73 63 72 69 70 74 69 6f 6e 22 3a 22 54 69 72 65 20 70 72 65 73 73 75 72 65 20 6d 6f 6e 69 74 6f 72
[54] 20 6d 6f 64 75 6c 65 22 2c 22 66 61 75 6c 74 49 6e 66 6f 72 6d 61 74 69 6f 6e 73 22 3a 5b 7b 22 64 65 73 63 72 69 70 74 69 6f 6e 22 3a 22 2d 2d 2d 22 7d 2c 7b
[107] 22 64 65 73 63 72 69 70 74 69 6f 6e 22 3a 22 54 52 55 45 22 2c 22 64 65 73 63 72 69 70 74 69 6f 6e 5f 65 6e 67 22 3a 22 54 52 55 45 22 2c 22 64 65 73 63 72 69
[160] 70 74 69 6f 6e 5f 66 72 65 22 3a 22 54 52 55 45 22 2c 22 64 65 73 63 72 69 70 74 69 6f 6e 5f 67 65 72 22 3a 22 54 52 55 45 22 2c 22 64 65 73 63 72 69 70 74 69
[213] 6f 6e 5f 73 70 61 22 3a 22 54 52 55 45 22 2c 22 64 65 73 63 72 69 70 74 69 6f 6e 5f 69 74 61 22 3a 22 54 52 55 45 22 2c 22 64 65 73 63 72 69 70 74 69 6f 6e 5f
[266] 74 75 72 22 3a 22 54 52 55 45 22 7d 5d 2c 22 66 72 65 65 7a 65 46 72 61 6d 65 73 22 3a 5b 5d 2c 22 65 6e 68 61 6e 63 65 64 44 74 63 49 6e 66 6f 73 22 3a 5b 5d
[319] 2c 22 73 74 61 74 75 73 22 3a 22 41 43 54 49 56 45 22 2c 22 73 79 73 74 65 6d 22 3a 22 4d 55 4c 54 49 46 55 4e 43 54 49 4f 4e 22 2c 22 73 79 73 74 65 6d 4d 65
[372] 74 61 22 3a 7b 22 73 79 73 74 65 6d 4e 61 6d 65 22 3a 6e 75 6c 6c 2c 22 73 75 62 53 79 73 74 65 6d 4e 61 6d 65 22 3a 6e 75 6c 6c 7d 2c 22 64 65 73 63 72 69 70
[425] 74 69 6f 6e 5f 65 6e 67 22 3a 22 54 69 72 65 20 70 72 65 73 73 75 72 65 20 6d 6f 6e 69 74 6f 72 20 6d 6f 64 75 6c 65 22 2c 22 64 65 73 63 72 69 70 74 69 6f 6e
[478] 5f 66 72 65 22 3a 22 4d 6f 64 75 6c 65 20 64 65 20 73 75 72 76 65 69 6c 6c 61 6e 63 65 20 64 65 20 6c 61 20 70 72 65 73 73 69 6f 6e 20 64 65 73 20 70 6e 65 75
[531] 73 22 2c 22 64 65 73 63 72 69 70 74 69 6f 6e 5f 67 65 72 22 3a 22 52 65 69 66 65 6e 64 72 75 63 6b c3 bc 62 65 72 77 61 63 68 75 6e 67 22 2c 22 64 65 73 63 72
[584] 69 70 74 69 6f 6e 5f 73 70 61 22 3a 22 4d c3 b3 64 75 6c 6f 20 64 65 20 63 6f 6e 74 72 6f 6c 20 64 65 20 6c 61 20 70 72 65 73 69 c3 b3 6e 20 64 65 20 6c 6f 73
[637] 20 6e 65 75 6d c3 a1 74 69 63 6f 73 22 2c 22 64 65 73 63 72 69 70 74 69 6f 6e 5f 69 74 61 22 3a 22 4d 6f 64 75 6c 6f 20 6d 6f 6e 69 74 6f 72 20 64 69 20 70 72
[690] 65 73 73 69 6f 6e 65 20 70 6e 65 75 6d 61 74 69 63 6f 22 2c 22 64 65 73 63 72 69 70 74 69 6f 6e 5f 74 75 72 22 3a 22 4c 61 73 74 69 6b 20 62 61 73 c4 b1 6e 63
[743] c4 b1 20 69 7a 6c 65 6d 65 20 6d 6f 64 c3 bc 6c c3 bc 22 7d 2c 7b 22 63 6f 64 65 22 3a 22 42 31 32 34 44 22 2c 22 64 65 73 63 72 69 70 74 69 6f 6e 22 3a 22 53
[796] 65 6e 73 6f 72 2c 20 74 79 72 65 20 70 72 65 73 73 75 72 65 22 2c 22 66 61 75 6c 74 49 6e 66 6f 72 6d 61 74 69 6f 6e 73 22 3a 5b 7b 22 64 65 73 63 72 69 70 74
[849] 69 6f 6e 22 3a 22 2d 2d 2d 22 7d 2c 7b 22 64 65 73 63 72 69 70 74 69 6f 6e 22 3a 22 54 52 55 45 22 2c 22 64 65 73 63 72 69 70 74 69 6f 6e 5f 65 6e 67 22 3a 22
[902] 54 52 55 45 22 2c 22 64 65 73 63 72 69 70 74 69 6f 6e 5f 66 72 65 22 3a 22 54 52 55 45 22 2c 22 64 65 73 63 72 69 70 74 69 6f 6e 5f 67 65 72 22 3a 22 54 52 55
[955] 45 22 2c 22 64 65 73 63 72 69 70 74 69 6f 6e 5f 73 70 61 22 3a 22 54 52 55 45 22 2c 22 64 65 73 63 72 69 70 74 69 6f 6e 5f 69 74 61 22 3a
However, when I copy that string into this web, I get this result:
[{"code":"B1182","description":"Tire pressure monitor module","faultInformations":[{"description":"---"},{"description":"TRUE","description_eng":"TRUE","description_fre":"TRUE","description_ger":"TRUE","description_spa":"TRUE","description_ita":"TRUE","description_tur":"TRUE"}],"freezeFrames":[],"enhancedDtcInfos":[],"status":"ACTIVE","system":"MULTIFUNCTION","systemMeta":{"systemName":null,"subSystemName":null},"description_eng":"Tire pressure monitor module","description_fre":"Module de surveillance de la pression des pneus","description_ger":"Reifendrucküberwachung","description_spa":"Módulo de control de la presión de los neumáticos","description_ita":"Modulo monitor di pressione pneumatico","description_tur":"Lastik basıncı izleme modülü"},{"code":"B124D","description":"Sensor, tyre pressure","faultInformations":[{"description":"---"},{"description":"TRUE","description_eng":"TRUE","description_fre":"TRUE","description_ger":"TRUE","description_spa":"TRUE","description_ita":"TRUE","description_tur":"TRUE"}],"freezeFrames":[],"enhancedDtcInfos":[],"status":"ACTIVE","system":"MULTIFUNCTION","systemMeta":{"systemName":null,"subSystemName":null},"description_eng":"Sensor, tyre pressure","description_fre":"Capteur, pression des pneus","description_ger":"Sensor Reifendruck","description_spa":"Sensor de presión del neumático","description_ita":"Sensore, pressione pneumatici","description_tur":"Sensör, lastik hava basıncı"}]
This is actually the expected output. What's wrong with the code?
Looks like the output is raw encoded. So you'll need to use rawToChar.
library(base64)
rawToChar(base64_decode(x))
[1] "[{\"code\":\"B1182\",\"description\":\"Tire pressure monitor module\",\"faultInformations\":[{\"description\":\"---\"},{\"description\":\"TRUE\",\"description_eng\":\"TRUE\",\"description_fre\":\"TRUE\",\"description_ger\":\"TRUE\",\"description_spa\":\"TRUE\",\"description_ita\":\"TRUE\",\"description_tur\":\"TRUE\"}],\"freezeFrames\":[],\"enhancedDtcInfos\":[],\"status\":\"ACTIVE\",\"system\":\"MULTIFUNCTION\",\"systemMeta\":{\"systemName\":null,\"subSystemName\":null},\"description_eng\":\"Tire pressure monitor module\",\"description_fre\":\"Module de surveillance de la pression des pneus\",\"description_ger\":\"Reifendrucküberwachung\",\"description_spa\":\"Módulo de control de la presión de los neumáticos\",\"description_ita\":\"Modulo monitor di pressione pneumatico\",\"description_tur\":\"Lastik basıncı izleme modülü\"},{\"code\":\"B124D\",\"description\":\"Sensor, tyre pressure\",\"faultInformations\":[{\"description\":\"---\"},{\"description\":\"TRUE\",\"description_eng\":\"TRUE\",\"description_fre\":\"TRUE\",\"description_ger\":\"TRUE\",\"description_spa\":\"TRUE\",\"description_ita\":\"TRUE\",\"description_tur\":\"TRUE\"}],\"freezeFrames\":[],\"enhancedDtcInfos\":[],\"status\":\"ACTIVE\",\"system\":\"MULTIFUNCTION\",\"systemMeta\":{\"systemName\":null,\"subSystemName\":null},\"description_eng\":\"Sensor, tyre pressure\",\"description_fre\":\"Capteur, pression des pneus\",\"description_ger\":\"Sensor Reifendruck\",\"description_spa\":\"Sensor de presión del neumático\",\"description_ita\":\"Sensore, pressione pneumatici\",\"description_tur\":\"Sensör, lastik hava basıncı\"}]"
Edit
To better understand why this is necessary we can check the class of the output of base64_decode().
> class(base64_decode(x))
#[1] "raw"
The ?raw helpfully tells us:
The raw type is intended to hold raw bytes. It is possible to extract subsequences of bytes, and to replace elements (but only by elements of a raw vector). ... A raw vector is printed with each byte separately represented as a pair of hex digits. If you want to see a character representation (with escape sequences for non-printing characters) use rawToChar.
So we just need to convert the raw bytes to character.
Data
x <- "W3siY29kZSI6IkIxMTgyIiwiZGVzY3JpcHRpb24iOiJUaXJlIHByZXNzdXJlIG1vbml0b3IgbW9kdWxlIiwiZmF1bHRJbmZvcm1hdGlvbnMiOlt7ImRlc2NyaXB0aW9uIjoiLS0tIn0seyJkZXNjcmlwdGlvbiI6IlRSVUUiLCJkZXNjcmlwdGlvbl9lbmciOiJUUlVFIiwiZGVzY3JpcHRpb25fZnJlIjoiVFJVRSIsImRlc2NyaXB0aW9uX2dlciI6IlRSVUUiLCJkZXNjcmlwdGlvbl9zcGEiOiJUUlVFIiwiZGVzY3JpcHRpb25faXRhIjoiVFJVRSIsImRlc2NyaXB0aW9uX3R1ciI6IlRSVUUifV0sImZyZWV6ZUZyYW1lcyI6W10sImVuaGFuY2VkRHRjSW5mb3MiOltdLCJzdGF0dXMiOiJBQ1RJVkUiLCJzeXN0ZW0iOiJNVUxUSUZVTkNUSU9OIiwic3lzdGVtTWV0YSI6eyJzeXN0ZW1OYW1lIjpudWxsLCJzdWJTeXN0ZW1OYW1lIjpudWxsfSwiZGVzY3JpcHRpb25fZW5nIjoiVGlyZSBwcmVzc3VyZSBtb25pdG9yIG1vZHVsZSIsImRlc2NyaXB0aW9uX2ZyZSI6Ik1vZHVsZSBkZSBzdXJ2ZWlsbGFuY2UgZGUgbGEgcHJlc3Npb24gZGVzIHBuZXVzIiwiZGVzY3JpcHRpb25fZ2VyIjoiUmVpZmVuZHJ1Y2vDvGJlcndhY2h1bmciLCJkZXNjcmlwdGlvbl9zcGEiOiJNw7NkdWxvIGRlIGNvbnRyb2wgZGUgbGEgcHJlc2nDs24gZGUgbG9zIG5ldW3DoXRpY29zIiwiZGVzY3JpcHRpb25faXRhIjoiTW9kdWxvIG1vbml0b3IgZGkgcHJlc3Npb25lIHBuZXVtYXRpY28iLCJkZXNjcmlwdGlvbl90dXIiOiJMYXN0aWsgYmFzxLFuY8SxIGl6bGVtZSBtb2TDvGzDvCJ9LHsiY29kZSI6IkIxMjREIiwiZGVzY3JpcHRpb24iOiJTZW5zb3IsIHR5cmUgcHJlc3N1cmUiLCJmYXVsdEluZm9ybWF0aW9ucyI6W3siZGVzY3JpcHRpb24iOiItLS0ifSx7ImRlc2NyaXB0aW9uIjoiVFJVRSIsImRlc2NyaXB0aW9uX2VuZyI6IlRSVUUiLCJkZXNjcmlwdGlvbl9mcmUiOiJUUlVFIiwiZGVzY3JpcHRpb25fZ2VyIjoiVFJVRSIsImRlc2NyaXB0aW9uX3NwYSI6IlRSVUUiLCJkZXNjcmlwdGlvbl9pdGEiOiJUUlVFIiwiZGVzY3JpcHRpb25fdHVyIjoiVFJVRSJ9XSwiZnJlZXplRnJhbWVzIjpbXSwiZW5oYW5jZWREdGNJbmZvcyI6W10sInN0YXR1cyI6IkFDVElWRSIsInN5c3RlbSI6Ik1VTFRJRlVOQ1RJT04iLCJzeXN0ZW1NZXRhIjp7InN5c3RlbU5hbWUiOm51bGwsInN1YlN5c3RlbU5hbWUiOm51bGx9LCJkZXNjcmlwdGlvbl9lbmciOiJTZW5zb3IsIHR5cmUgcHJlc3N1cmUiLCJkZXNjcmlwdGlvbl9mcmUiOiJDYXB0ZXVyLCBwcmVzc2lvbiBkZXMgcG5ldXMiLCJkZXNjcmlwdGlvbl9nZXIiOiJTZW5zb3IgUmVpZmVuZHJ1Y2siLCJkZXNjcmlwdGlvbl9zcGEiOiJTZW5zb3IgZGUgcHJlc2nDs24gZGVsIG5ldW3DoXRpY28iLCJkZXNjcmlwdGlvbl9pdGEiOiJTZW5zb3JlLCBwcmVzc2lvbmUgcG5ldW1hdGljaSIsImRlc2NyaXB0aW9uX3R1ciI6IlNlbnPDtnIsIGxhc3RpayBoYXZhIGJhc8SxbmPEsSJ9XQ=="
I am trying to get readings from an ultrasonic thickness tester without using the included software, but I haven't been able to interpret the measurement readings from the tester.
Below are the hex values that are sent from the tester, and the corresponding decimal value that is displayed in the software.
3A 30 62 30 30 44 39 37 30 30 65 36 0D 0A 1.51
3A 30 62 30 30 44 66 61 30 30 34 39 0D 0A 2.50
3A 30 62 30 30 44 37 62 30 31 63 62 0D 0A 3.79
3A 30 62 30 30 44 38 32 30 31 64 32 0D 0A 3.86
3A 30 62 30 30 44 63 37 30 31 31 37 0D 0A 4.55
3A 30 62 30 30 44 39 34 30 62 65 65 0D 0A 29.64
3A 30 62 30 30 44 39 63 30 62 66 36 0D 0A 29.72
3A 30 62 30 30 44 63 61 30 62 32 34 0D 0A 30.18
3A 30 62 30 30 44 65 64 30 62 34 37 0D 0A 30.53
3A 30 62 30 30 44 38 65 33 65 31 62 0D 0A 160.14
3A 30 62 30 30 44 64 66 33 65 36 63 0D 0A 160.95
Any help on how I get from the hex values to the decimal value would be very much appreciated.
ASCII equivalent (I have omitted CR and LF which are at the end of each line) :
:0b00D9700e6 1.51
:0b00Dfa0049 2.50
:0b00D7b01cb 3.79
:0b00D8201d2 3.86
:0b00Dc70117 4.55
:0b00D940bee 29.64
:0b00D9c0bf6 29.72
:0b00Dca0b24 30.18
:0b00Ded0b47 30.53
:0b00D8e3e1b 160.14
:0b00Ddf3e6c 160.95
Finally figured it out:
The data is the two bytes after :0b00D, LSB first, multiplied by 100.
ASCII Hex Decimal
:0b00D9700e6 0097 1.51
:0b00Dfa0049 00fa 2.50
:0b00D7b01cb 017b 3.79
:0b00D8201d2 0182 3.86
:0b00Dc70117 01c7 4.55
:0b00D940bee 0b94 29.64
:0b00D9c0bf6 0b9c 29.72
:0b00Dca0b24 0bca 30.18
:0b00Ded0b47 0bed 30.53
:0b00D8e3e1b 3e8e 160.14
:0b00Ddf3e6c 3edf 160.95
I am trying to decrypt the PaymentToken returned by ApplePay with OpenSSL. The decryption works but I am seeing an extra 16 bytes appended to the plaintext as well as an error during EVP_DecryptFinal_ex. My first thought was I needed to turn off padding but that does not seem to be the issue. Any help is appreciated!
Apple's docs say:
Use the symmetric key to decrypt the value of the data key using AES–256 (id-aes256-GCM 2.16.840.1.101.3.4.1.46), with an initialization vector of sixteen null bytes and no associated authentication data.
The java sample provided by Apple uses BouncyCastle and initializes the Cipher with "AES/GCM/NoPadding"
My code looks like this:
static const unsigned char gcm_iv[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
/* Create the context */
EVP_CIPHER_CTX *decrypt_ctx;
decrypt_ctx = EVP_CIPHER_CTX_new();
/* Select cipher */
EVP_DecryptInit_ex(decrypt_ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
/* Set IV length */
EVP_CIPHER_CTX_ctrl(decrypt_ctx, EVP_CTRL_GCM_SET_IVLEN, sizeof(gcm_iv), NULL);
/* Specify key and IV */
EVP_DecryptInit_ex(decrypt_ctx, NULL, NULL, (const unsigned char *)gcm_key, gcm_iv);
/* Turn off padding */
EVP_CIPHER_CTX_set_padding(decrypt_ctx, 0);
unsigned char outbuf[4096];
int outlen = sizeof(outbuf);
int rv;
int plaintext_len;
/* Decrypt plaintext */
rv = EVP_DecryptUpdate(decrypt_ctx, outbuf, &outlen, (const unsigned char *)data, data_length);
if(!rv)
{
printf("\nOpenSSL Error after DecryptUpdate: %s\n", ERR_error_string(ERR_get_error(), NULL));
err = 1;
}
/* Output decrypted block */
printf("\nPlaintext after DecryptUpdate (%d bytes):\n\n", outlen);
/* Remember plaintext length */
plaintext_len = outlen;
BIO_dump_fp(stdout, (const char *)outbuf, plaintext_len);
rv = EVP_DecryptFinal_ex(decrypt_ctx, outbuf + outlen, &outlen);
if(!rv)
{
printf("\nOpenSSL Error after DecryptFinal_ex: %s\n", ERR_error_string(ERR_get_error(), NULL));
err = 1;
}
/* Output decrypted block */
printf("\nPlaintext after DecryptFinal(%d bytes):\n\n", outlen);
BIO_dump_fp(stdout, (const char *)outbuf, plaintext_len);
And the output looks like this (plaintext altered for security):
Plaintext after DecryptUpdate (319 bytes):
0000 - 7b 22 61 70 70 6c 69 63-61 74 69 6f 6e 50 72 69 {"applicationPri
0010 - 6d 61 72 79 41 63 63 6f-75 6e 74 4e 75 6d 62 65 maryAccountNumbe
0020 - 72 22 3a 22 34 30 38 38-xx xx xx xx xx xx xx xx r":"4088xxxxxxxx
0030 - 30 30 32 32 22 2c 22 61-70 70 6c 69 63 61 74 69 0022","applicati
0040 - 6f 6e 45 78 70 69 72 61-74 69 6f 6e 44 61 74 65 onExpirationDate
0050 - 22 3a 22 32 30 30 32 32-38 22 2c 22 63 75 72 72 ":"200228","curr
0060 - 65 6e 63 79 43 6f 64 65-22 3a 22 38 34 30 22 2c encyCode":"840",
0070 - 22 74 72 61 6e 73 61 63-74 69 6f 6e 41 6d 6f 75 "transactionAmou
0080 - 6e 74 22 3a 33 30 30 2c-22 64 65 76 69 63 65 4d nt":300,"deviceM
0090 - 61 6e 75 66 61 63 74 75-72 65 72 49 64 65 6e 74 anufacturerIdent
00a0 - 69 66 69 65 72 22 3a 22-xx xx xx xx xx xx xx xx ifier":"xxxxxxxx
00b0 - xx xx xx xx 22 2c 22 70-61 79 6d 65 6e 74 44 61 xxxx","paymentDa
00c0 - 74 61 54 79 70 65 22 3a-22 33 44 53 65 63 75 72 taType":"3DSecur
00d0 - 65 22 2c 22 70 61 79 6d-65 6e 74 44 61 74 61 22 e","paymentData"
00e0 - 3a 7b 22 6f 6e 6c 69 6e-65 50 61 79 6d 65 6e 74 :{"onlinePayment
00f0 - 43 72 79 70 74 6f 67 72-61 6d 22 3a 22 xx xx xx Cryptogram":"xxx
0100 - xx xx xx xx xx xx xx xx-xx xx xx xx xx xx xx xx xxxxxxxxxxxxxxxx
0110 - xx xx xx xx xx xx xx xx-xx 22 2c 22 65 63 69 49 xxxxxxxxx","eciI
0120 - 6e 64 69 63 61 74 6f 72-22 3a 22 35 22 7d 7d 0b ndicator":"5"}}.
0130 - ce 56 54 48 49 1c 73 1a-b3 a4 89 e8 b2 11 f7 .VTHI.s........
OpenSSL Error after DecryptFinal_ex: error:00000000:lib(0):func(0):reason(0)
Plaintext after DecryptFinal(0 bytes):
0000 - 7b 22 61 70 70 6c 69 63-61 74 69 6f 6e 50 72 69 {"applicationPri
0010 - 6d 61 72 79 41 63 63 6f-75 6e 74 4e 75 6d 62 65 maryAccountNumbe
0020 - 72 22 3a 22 34 30 38 38-xx xx xx xx xx xx xx xx r":"4088xxxxxxxx
0030 - 30 30 32 32 22 2c 22 61-70 70 6c 69 63 61 74 69 0022","applicati
0040 - 6f 6e 45 78 70 69 72 61-74 69 6f 6e 44 61 74 65 onExpirationDate
0050 - 22 3a 22 32 30 30 32 32-38 22 2c 22 63 75 72 72 ":"200228","curr
0060 - 65 6e 63 79 43 6f 64 65-22 3a 22 38 34 30 22 2c encyCode":"840",
0070 - 22 74 72 61 6e 73 61 63-74 69 6f 6e 41 6d 6f 75 "transactionAmou
0080 - 6e 74 22 3a 33 30 30 2c-22 64 65 76 69 63 65 4d nt":300,"deviceM
0090 - 61 6e 75 66 61 63 74 75-72 65 72 49 64 65 6e 74 anufacturerIdent
00a0 - 69 66 69 65 72 22 3a 22-xx xx xx xx xx xx xx xx ifier":"xxxxxxxx
00b0 - xx xx xx xx 22 2c 22 70-61 79 6d 65 6e 74 44 61 xxxx","paymentDa
00c0 - 74 61 54 79 70 65 22 3a-22 33 44 53 65 63 75 72 taType":"3DSecur
00d0 - 65 22 2c 22 70 61 79 6d-65 6e 74 44 61 74 61 22 e","paymentData"
00e0 - 3a 7b 22 6f 6e 6c 69 6e-65 50 61 79 6d 65 6e 74 :{"onlinePayment
00f0 - 43 72 79 70 74 6f 67 72-61 6d 22 3a 22 xx xx xx Cryptogram":"xxx
0100 - xx xx xx xx xx xx xx xx-xx xx xx xx xx xx xx xx xxxxxxxxxxxxxxxx
0110 - xx xx xx xx xx xx xx xx-xx 22 2c 22 65 63 69 49 xxxxxxxxx","eciI
0120 - 6e 64 69 63 61 74 6f 72-22 3a 22 35 22 7d 7d 0b ndicator":"5"}}.
0130 - ce 56 54 48 49 1c 73 1a-b3 a4 89 e8 b2 11 f7 .VTHI.s........
I'm trying to create HTTP request to XML service and I'm getting 400 errors from IIS server.
This request WORKS:
T 192.168.0.10:52584 -> 193.189.144.141:80 [AP]
50 4f 53 54 20 2f 73 63 72 69 70 74 73 2f 58 4d POST /scripts/XM
4c 5f 49 6e 74 65 72 66 61 63 65 2e 64 6c 6c 20 L_Interface.dll
48 54 54 50 2f 31 2e 30 0d 0a HTTP/1.0..
###
T 192.168.0.10:52584 -> 193.189.144.141:80 [AP]
48 6f 73 74 3a 20 77 77 77 31 2e 67 6e 74 2e 6c Host: www1.gnt.l
74 0d 0a 43 6f 6e 74 65 6e 74 2d 74 79 70 65 3a t..Content-type:
20 61 70 70 6c 69 63 61 74 69 6f 6e 2f 78 2d 77 application/x-w
77 77 2d 66 6f 72 6d 2d 75 72 6c 65 6e 63 6f 64 ww-form-urlencod
65 64 0d 0a 43 6f 6e 74 65 6e 74 2d 6c 65 6e 67 ed..Content-leng
74 68 3a 20 37 33 0d 0a 43 6f 6e 6e 65 63 74 69 th: 73..Connecti
6f 6e 3a 20 63 6c 6f 73 65 0d 0a 0d 0a 4d 66 63 on: close....Mfc
49 53 41 50 49 43 6f 6d 6d 61 6e 64 3d 44 65 66 ISAPICommand=Def
61 75 6c 74 26 55 53 45 52 4e 41 4d 45 3d 73 65 ault&USERNAME=se
63 72 65 74 26 50 41 53 53 57 4f 52 44 3d 73 65 cret&PASSWORD=se
63 72 65 74 26 43 48 45 43 4b 3d 73 65 63 72 65 cret&CHECK=secre
74 26 58 4d 4c 3d 0d 0a 0d 0a t&XML=....
Although this one DOESN'T WORK:
T 192.168.0.10:52592 -> 193.189.144.141:80 [AP]
50 4f 53 54 20 2f 73 63 72 69 70 74 73 2f 58 4d POST /scripts/XM
4c 5f 49 6e 74 65 72 66 61 63 65 2e 64 6c 6c 20 L_Interface.dll
48 54 54 50 2f 31 2e 30 0d 0a 43 6f 6e 74 65 6e HTTP/1.0..Conten
74 2d 54 79 70 65 3a 20 61 70 70 6c 69 63 61 74 t-Type: applicat
69 6f 6e 2f 78 2d 77 77 77 2d 66 6f 72 6d 2d 75 ion/x-www-form-u
72 6c 65 6e 63 6f 64 65 64 0d 0a 43 6f 6e 74 65 rlencoded..Conte
6e 74 2d 4c 65 6e 67 74 68 3a 20 37 32 0d 0a 48 nt-Length: 72..H
6f 73 74 3a 20 77 77 77 31 2e 67 6e 74 2e 6c 74 ost: www1.gnt.lt
0d 0a 55 73 65 72 2d 41 67 65 6e 74 3a 20 50 79 ..User-Agent: Py
74 68 6f 6e 2d 75 72 6c 6c 69 62 2f 31 2e 31 37 thon-urllib/1.17
0d 0a 0d 0a 58 4d 4c 3d 26 55 53 45 52 4e 41 4d ....XML=&USERNAM
45 3d 73 65 63 72 65 74 26 50 41 53 53 57 4f 52 E=secret&PASSWOR
44 3d 73 65 63 72 65 74 26 4d 66 63 49 53 41 50 D=secret&MfcISAP
49 43 6f 6d 6d 61 6e 64 3d 44 65 66 61 75 6c 74 ICommand=Default
26 43 48 45 43 4b 3d 63 68 65 63 6b &CHECK=check
Exact error message:
HTTP/1.1 400 Bad Request.
Server: Microsoft-IIS/6.0.
X-Powered-By: ASP.NET.
Date: Wed, 13 Jul 2011 20:53:07 GMT.
Connection: close.
.
Any ideas where's the issue?
Resolved by changing order of arguments.
Made MfcISAP=Default the first argument