Convert QR decoding solution from Python to C# (EU DGC) - python

I am trying to convert this Python code to C# (.NET Core ideally).
Source
My goal is to convert the QR input string to another string containing the data in json. See the provided links.
#! /usr/bin/env python3
import json
import sys
import zlib
import base45
import cbor2
from cose.messages import CoseMessage
payload = sys.argv[1][4:]
print("decoding payload: "+ payload)
# decode Base45 (remove HC1: prefix)
decoded = base45.b45decode(payload)
# decompress using zlib
decompressed = zlib.decompress(decoded)
# decode COSE message (no signature verification done)
cose = CoseMessage.decode(decompressed)
# decode the CBOR encoded payload and print as json
print(json.dumps(cbor2.loads(cose.payload), indent=2))
I couldn't find any NuGet package for Zlib, that would work correctly. So I am stuck straight after base45 decoding. Thanks for any tips.
using System.Text; //Rystem.Text.Base45 NuGet
var removedHeader = testQrData.Substring(4);
var decoded = removedHeader.FromBase45();
byte[] rawBytes = Encoding.ASCII.GetBytes(decoded);
This link might be helpful for further investigation.
Decoding scheme

IBarcodeReader reader = new BarcodeReader();//using Zxing
var barcodeBitmap = (Bitmap)Bitmap.FromFile("qrcode.png");
var barcodeReader = new BarcodeReader();
var qrcontent = barcodeReader.Decode(barcodeBitmap).Text;
var qrmessage = qrcontent.Substring(4);//remove first 4 chars
byte[] decodedBase45 = Base45Encoding.Decode(qrmessage);//using base45 lib
var cose = ZlibStream.UncompressBuffer(decodedBase45);//using zlib or similar
var decrypted = Message.DecodeFromBytes(cose).GetContent(); //using COSE
CBORObject cbor = CBORObject.DecodeFromBytes(decrypted); //using Peter.O.. CBOR
var jsonDecoded = cbor.ToJSONString(); //or deserialize it to custom class

I added "Zlib.Portable" from NuGet and used "ZlibStream.UncompressString"
byte[] decoded = Base45Encoding.Decode(input);
var stringResult = ZlibStream.UncompressString(decoded);`
I'm stuck in the next step "CoseMessage.decode" :/

I have used the ZXing library in the past to decode and create QR Codes:
https://github.com/micjahn/ZXing.Net
You could also try: https://github.com/codebude/QRCoder
A quick ZXing example from their github page:
// create a barcode reader instance
IBarcodeReader reader = new BarcodeReader();
// load a bitmap
var barcodeBitmap = (Bitmap)Image.LoadFrom("C:\\sample-barcode-image.png");
// detect and decode the barcode inside the bitmap
var result = reader.Decode(barcodeBitmap);
// do something with the result
if (result != null)
{
txtDecoderType.Text = result.BarcodeFormat.ToString();
txtDecoderContent.Text = result.Text;
}
This example reads a QR Code image.
I'm not sure what your input is but i would assume it's also an image in binary format so you might have to play around to get it working.

This solution works for me.
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
using System;
using System.IO;
using Com.AugustCellars.COSE;
using PeterO.Cbor;
using Newtonsoft.Json;
using Microsoft.Extensions.Logging;
using System.Linq;
using System.Collections.Generic;
namespace DGCVerification.Services {
public class DGCVerificationService: IDGCVerificationService {
private readonly string _certificatePrefix = "HC1:";
private readonly ILogger < DGCVerificationService > _logger;
public DGCVerificationService(ILogger < DGCVerificationService > logger) {
_logger = logger;
}
private bool TryTrimPrefix(string certificateString, out string result) {
if (!certificateString.StartsWith(_certificatePrefix)) {
result = null;
return false;
}
result = certificateString.Substring(_certificatePrefix.Length);
return true;
}
private byte[] DecompressFromZlib(byte[] input) {
using(var memoryStream = new MemoryStream(input)) {
using(var decompressionStream = new InflaterInputStream(memoryStream)) {
using(var resultStream = new MemoryStream()) {
decompressionStream.CopyTo(resultStream);
var result = resultStream.ToArray();
return result;
}
}
}
}
private bool VerifyCoseSignature(Sign1Message coseMessage, string signature) {
var signatureAsBytes = Convert.FromBase64String(signature);
var publicKey = OneKey.FromX509(signatureAsBytes);
var result = coseMessage.Validate(publicKey);
_logger.LogInformation($"cose message signature {signature} verified as {result}");
return result;
}
private DGCPayload DecodeAndDeserialize(string certificateString, out Sign1Message coseMessage) {
coseMessage = null;
if (!TryTrimPrefix(certificateString, out
var trimmedPrefixString)) {
_logger.LogInformation($"certificate {certificateString} didn't have proper prefix {_certificatePrefix}");
return null;
}
var bytesBase256 = Base45Encoding.Decode(trimmedPrefixString);
_logger.LogInformation($"certificate {certificateString} base45 decoded to {Convert.ToBase64String(bytesBase256)}");
var decompressedFromZlib = DecompressFromZlib(bytesBase256);
_logger.LogDebug($"certificate {certificateString} zlib decompressed to {Convert.ToBase64String(decompressedFromZlib)}");
coseMessage = Message.DecodeFromBytes(decompressedFromZlib) as Sign1Message;
var coseMessagePayload = coseMessage.GetContent();
var cborResult = CBORObject.DecodeFromBytes(coseMessagePayload);
var jsonResult = cborResult.ToJSONString();
var result = JsonConvert.DeserializeObject < DGCPayloadCzechVersionRoot > (jsonResult);
return result.DGCPayloadWrap.DGCPayload;
}
private bool IsNotExpiredDGC(DGCPayload dGCPayload, UzisData uzisData) {
var vaccine = dGCPayload.Vaccination?.FirstOrDefault();
if (vaccine != null) {
var vaccinationValidityRules = uzisData.DGCValidityCzechRules.Rules
.FirstOrDefault()
.PlatnostiVakcinace;
var rule = vaccinationValidityRules.FirstOrDefault(x => x.VaccineMedicinalProduct == vaccine.Mp) ??
vaccinationValidityRules.FirstOrDefault(x => x.VaccineMedicinalProduct == null);
if (!DateTime.TryParse(vaccine.Dt, out
var vaccinatedOnDate)) {
_logger.LogError($"couldn't parse date of vaccination for DGC : {JsonConvert.SerializeObject(dGCPayload)}");
return false;
}
var result = DateTime.Now.Date <= vaccinatedOnDate.AddMonths(rule.OdolnostMesicDo);
return result;
}
var test = dGCPayload.Test?.FirstOrDefault();
if (test != null) {
var testValidityRule = uzisData.DGCValidityCzechRules.Rules
.FirstOrDefault()
.PlatnostiTestu
.FirstOrDefault(x => x.TypeOfTest == test.Tt);
if (!DateTime.TryParse(test.Tr, out
var testedOnDate)) {
_logger.LogError($"couldn't parse date of test for DGC : {JsonConvert.SerializeObject(dGCPayload)}");
return false;
}
var result = DateTime.Now.Date <= testedOnDate.AddHours(testValidityRule.PlatnostHod);
return result;
}
var recovery = dGCPayload.Recovery?.FirstOrDefault();
if (recovery != null) {
if (!DateTime.TryParse(recovery.Du, out
var recoveryValidUntil)) {
_logger.LogError($"couldn't parse recovert valid until for DGC : {JsonConvert.SerializeObject(dGCPayload)}");
return false;
}
var result = DateTime.Now.Date <= recoveryValidUntil;
return result;
}
return false;
}
private string GetCountryFromDGC(DGCPayload dGCPayload) {
var result = dGCPayload.Vaccination?.FirstOrDefault()?.Co ??
dGCPayload.Test?.FirstOrDefault()?.Co ??
dGCPayload.Recovery?.FirstOrDefault()?.Co;
if (result == null) {
throw new ArgumentException($"couldn't retrieve country from DGC. dgc : {JsonConvert.SerializeObject(dGCPayload)}");
}
return result;
}
private List < SignatureCertificate > GetFittingSignatures(DGCPayload dGCPayload, UzisData uzisData) {
try {
var country = GetCountryFromDGC(dGCPayload);
var result = uzisData.NationalCertificateSignatures.SignatureCertificate
.Where(x => x.Active)
.Where(x => x.Country == country)
.Where(x => x.CertificateType == "DSC")
.ToList();
return result;
} catch (Exception e) {
_logger.LogError(e, $"Filtering signatures from UZIS failed with exception");
return null;
}
}
private bool IsProperlySignedDGC(string certificateString, DGCPayload dGCPayload, Sign1Message coseMessage, UzisData uzisData) {
var fittingSignatures = GetFittingSignatures(dGCPayload, uzisData);
var result = false;
foreach(var signature in fittingSignatures) {
try {
var signatureVerificationResult = VerifyCoseSignature(coseMessage, signature.RawData);
_logger.LogInformation($"certificate {certificateString} signature validation against signature {signature} resulted in {signatureVerificationResult}");
result |= signatureVerificationResult;
} catch (Exception e) {
_logger.LogError(e, $"certificate {certificateString} signature validation against signature {signature} failed with exception");
}
}
return result;
}
public bool IsValidDgc(string certificateString, UzisData uzisData, out DGCPayload decodedDGCPayload, out VerificationResult verificationResult) {
decodedDGCPayload = null;
Sign1Message coseMessage = null;
try {
decodedDGCPayload = DecodeAndDeserialize(certificateString, out coseMessage);
if (coseMessage == null) {
_logger.LogInformation($"certificate {certificateString} decoded to null COSE");
verificationResult = VerificationResult.UnableToDecode;
return false;
}
} catch (Exception e) {
_logger.LogError(e, $"certificate {certificateString} decoding failed with exception");
verificationResult = VerificationResult.UnableToDecode;
return false;
}
var isProperlySigned = IsProperlySignedDGC(certificateString, decodedDGCPayload, coseMessage, uzisData);
if (!isProperlySigned) {
verificationResult = VerificationResult.InvalidSignature;
return false;
}
var isNotExpired = IsNotExpiredDGC(decodedDGCPayload, uzisData);
if (!isNotExpired) {
verificationResult = VerificationResult.Expired;
return false;
}
verificationResult = VerificationResult.Valid;
return true;
}
}
}
And the tricky base45
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DGCVerification
{
public class Base45Encoding
{
private static readonly Dictionary<byte, char> _encodingTable = new Dictionary<byte, char>
{
{0x0,'0'},
{0x1,'1'},
{0x2,'2'},
{0x3,'3'},
{0x4,'4'},
{0x5,'5'},
{0x6,'6'},
{0x7,'7'},
{0x8,'8'},
{0x9,'9'},
{0xA,'A'},
{0xB,'B'},
{0xC,'C'},
{0xD,'D'},
{0xE,'E'},
{0xF,'F'},
{0x10,'G'},
{0x11,'H'},
{0x12,'I'},
{0x13,'J'},
{0x14,'K'},
{0x15,'L'},
{0x16,'M'},
{0x17,'N'},
{0x18,'O'},
{0x19,'P'},
{0x1A,'Q'},
{0x1B,'R'},
{0x1C,'S'},
{0x1D,'T'},
{0x1E,'U'},
{0x1F,'V'},
{0x20,'W'},
{0x21,'X'},
{0x22,'Y'},
{0x23,'Z'},
{0x24,' '},
{0x25,'$'},
{0x26,'%'},
{0x27,'*'},
{0x28,'+'},
{0x29,'-'},
{0x2A,'.'},
{0x2B,'/'},
{0x2C,':'},
};
private static readonly Dictionary<char, byte> _decodingTable;
static Base45Encoding()
{
_decodingTable = _encodingTable.ToDictionary(x => x.Value, x => x.Key);
}
private static List<byte> ToBytesBase45(string charsBase45)
{
var result = new List<byte>(charsBase45.Length);
foreach (var character in charsBase45)
{
if (!_decodingTable.TryGetValue(character, out byte asByte))
{
throw new FormatException($"input string contains {character} with numeric value {char.GetNumericValue(character)} on index {charsBase45.IndexOf(character)} which is not valid base45 character");
}
result.Add(asByte);
}
return result;
}
private static List<ushort> ToShortsBase10(List<byte> bytesBase45)
{
var result = new List<ushort>(bytesBase45.Count);
ushort num = 0;
double pow = 0;
for (int i = 0; i != bytesBase45.Count; ++i, ++pow)
{
num += (ushort)(bytesBase45[i] * Math.Pow(45, pow));
if (pow == 2 || i == (bytesBase45.Count -1))
{
result.Add(num);
num = 0;
pow = -1;
}
}
return result;
}
private static List<byte> ToBytesBase256(List<ushort> shortsBase10, int charBase45Length)
{
var result = new List<byte>(shortsBase10.Count);
for (int i = 0; i != shortsBase10.Count; ++i)
{
var num = (byte)(shortsBase10[i] / 256);
if(!(i == (shortsBase10.Count - 1)
&& charBase45Length % 3 != 0
&& num == 0))
{
result.Add(num);
}
result.Add((byte)(shortsBase10[i] % 256));
}
return result;
}
public static byte[] Decode(string charsBase45)
{
if (charsBase45.Length % 3 == 1)
{
throw new FormatException("input string does not have correct length. mod 3 == 1. it isnt base45");
}
var bytesBase45 = ToBytesBase45(charsBase45);
var shortsBase10 = ToShortsBase10(bytesBase45);
var bytesBase256 = ToBytesBase256(shortsBase10, charsBase45.Length);
return bytesBase256.ToArray();
}
}
}

Decode/encode base45:
/// <summary>
/// https://tools.ietf.org/html/draft-faltstrom-baseBaseSize-01
/// TL/DR:
/// This encoding takes a byte array, splits it into 2 byte chunks and encodes each chunk as 3 characters.
/// Any remaining byte is encoded as 2 characters, padded with a '0' when the remaining byte has value < 45.
/// </summary>
public static class Base45Encoding
{
private const int BaseSize = 45;
private const int BaseSizeSquared = 2025;
private const int ChunkSize = 2;
private const int EncodedChunkSize = 3;
private const int SmallEncodedChunkSize = 2;
private const int ByteSize = 256;
private static readonly char[] _Encoding = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', ' ', '$', '%', '*',
'+', '-', '.', '/', ':' };
private static readonly Dictionary<char, byte> _Decoding = new(BaseSize);
static Base45Encoding()
{
for(byte i = 0; i < _Encoding.Length; ++i)
_Decoding.Add(_Encoding[i], i);
}
public static string Encode(byte[] buffer)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer));
var wholeChunkCount = buffer.Length / ChunkSize;
var result = new char[wholeChunkCount * EncodedChunkSize + (buffer.Length % ChunkSize == 1 ? SmallEncodedChunkSize : 0)];
if (result.Length == 0)
return string.Empty;
var resultIndex = 0;
var wholeChunkLength = wholeChunkCount * ChunkSize;
for (var i = 0; i < wholeChunkLength;)
{
var value = buffer[i++] * ByteSize + buffer[i++];
result[resultIndex++] = _Encoding[value % BaseSize];
result[resultIndex++] = _Encoding[value / BaseSize % BaseSize];
result[resultIndex++] = _Encoding[value / BaseSizeSquared % BaseSize];
}
if (buffer.Length % ChunkSize == 0)
return new string(result);
result[^2] = _Encoding[buffer[^1] % BaseSize];
result[^1] = buffer[^1] < BaseSize ? _Encoding[0] : _Encoding[buffer[^1] / BaseSize % BaseSize];
return new string(result);
}
public static byte[] Decode(string value)
{
if (value == null)
throw new ArgumentNullException(nameof(value));
if (value.Length == 0)
return Array.Empty<byte>();
var remainderSize = value.Length % EncodedChunkSize;
if (remainderSize == 1)
throw new FormatException("Incorrect length.");
var buffer = new byte[value.Length];
for (var i = 0; i < value.Length; ++i)
{
if (_Decoding.TryGetValue(value[i], out var decoded))
{
buffer[i] = decoded;
continue; //Earliest return on expected path.
}
throw new FormatException($"Invalid character at position {i}.");
}
var wholeChunkCount = buffer.Length / EncodedChunkSize;
var result = new byte[wholeChunkCount * ChunkSize + (remainderSize == ChunkSize ? 1 : 0)];
var resultIndex = 0;
var wholeChunkLength = wholeChunkCount * EncodedChunkSize;
for (var i = 0; i < wholeChunkLength; )
{
var val = buffer[i++] + BaseSize * buffer[i++] + BaseSizeSquared * buffer[i++];
result[resultIndex++] = (byte)(val / ByteSize); //result is always in the range 0-255 - % ByteSize omitted.
result[resultIndex++] = (byte)(val % ByteSize);
}
if (remainderSize == 0)
return result;
result[^1] = (byte)(buffer[^2] + BaseSize * buffer[^1]); //result is always in the range 0-255 - % ByteSize omitted.
return result;
}
}

Related

How can I convert CSV to JSON with data type in python or node.js?

I wanna convert CSV to JSON correct data type
csv file 2nd row is data type.
data has over 300 properties
example data:
Name
DMG
HP
Human
string
number
number
boolean
knight
100
500
true
archer
50
200
true
dog
-
-
-
if string empty return null
if number empty return 0
if boolean empty return false
my node.js code:
const fs = require('fs')
const papa = require("papaparse")
const results = [];
const options = { header: true, dynamicTyping: true };
fs.createReadStream("characters.csv")
.pipe(papa.parse(papa.NODE_STREAM_INPUT, options))
.on("data", (data) => {
results.push(data);
}).on("end", () => {
console.log(results)
})
output I expecting:
[
{
"Name": "knight",
"DMG": 100,
"HP": 500,
"Human": true,
},
{
"Name": "archer",
"DMG": 50,
"HP": 200,
"Human": true,
},
{
"Name": "dog",
"DMG": 0,
"HP": 0,
"Human": false,
},
]
Options options..
in this approach I cached the headerTypes and made a small helper function to return the intended type
define the vars let i = 0, headerTypes = {};
replace your on.data code with this
.on("data", (data) => {
if(i > 0){
for(let prop in data){
if(data.hasOwnProperty(prop)){
const value = data[prop];
data[prop] = typecast(headerTypes[prop], value);
}
}
}else{
//save types from row 0
headerTypes = data;
}
i++;
})
add this helper function
function typecast(type = '', value){
switch(type){
case "number":
return +value || 0; //unary for int or float
case "boolean":
return value === !0; //typecast to Boolean will let any filled string like '-' be true, do this instead.
case "string":
default:
return String(value);
}
}
Try overriding the properties in the on.data event like so
let i = 0; //define this outside, its only to skip that first row with headers.
if(i > 0){ //skipping first row
data.DMG = parseInt(data.DMG) || 0; //an int or 0
data.HP = parseInt(data.HP) || 0; //an int or 0
data.Human = data.Human === !0; //!0 = not false, will match true string or bool
results.push(data);
}
i++;//iterate
const fs = require('fs')
const papa = require("papaparse")
const results = [];
const options = { header: true, dynamicTyping: true };
let i = 0;
fs.createReadStream("characters.csv")
.pipe(papa.parse(papa.NODE_STREAM_INPUT, options))
.on("data", (data) => {
//add this here
if(i > 0){
data.DMG = parseInt(data.DMG) || 0; //an int or 0
data.HP = parseInt(data.HP) || 0; //an int or 0
data.Human = data.Human === !0; //!0 = not false, will match true string or bool
results.push(data);
}
i++;
//end add this here
}).on("end", () => {
console.log(results)
})

ElasticSearch Painless script: Not able to access nested objects using script score

I want to search for keywords from the specific field and return the documents. On top of these documents, I want to iterate through each nested object and search for keywords again from the same specific field on selected documents.
If a keyword exists, then check:
if boolean isCurrent = True, set isCurrent=0 and append this value to list
else if isCurrent = False, take the difference of current datetime, end datetime and get the value in terms of months and append this value to the list.
Finally, get the minimum value from that list of each document and sort the documents based on the minimum value.
I am able to do this custom login through script_fields and sort the documents based on the minimum value. When I use this same login in script_score it does not work. When I debug I see a problem accessing the nested field using params._source.
Any help will be much appreciated.
Please find the below elastic search query using script_fields. Here I am passing the current_milliseconds value from a python script.
query = {
'query': {
"nested": {
"path": "person.experiences",
"query": {
"query_string": {
"query": keywords,
"fields": ["person.experiences.description"],
"default_operator": "AND"
}
}
}
},
"script_fields": {
"recency": {
"script": {
"lang": "painless",
"inline": """
def myString = "";
def isCurrent = 0;
def isFound = false;
def index_position = 0;
def recency_num = 0;
def result = 0;
def list = new ArrayList();
// for loop starts here
for(int i=0; i<params._source.person.experiences.size(); i++){
myString = params._source.person.experiences[i].description;
// string match starts here
if(myString != null && myString != ''){
def matcher1 = /electric/.matcher(myString.toLowerCase());
def matcher2 = /vehicle/.matcher(myString.toLowerCase());
//if(wordMatcher.find()){
if (matcher1.find() || matcher2.find()){
isFound = true;
}
if (isFound == true){
// recency check starts here
isCurrent = params._source.person.experiences[i].isCurrent;
if(isCurrent == true){
isCurrent=0;
result+=isCurrent;
list.add(isCurrent);
} else{
ZonedDateTime now = ZonedDateTime.ofInstant(Instant.ofEpochMilli(params['current_datetime']), ZoneId.of('Z'));
ZonedDateTime end_date = ZonedDateTime.parse(params._source.person.experiences[i].end);
isCurrent = end_date.until(now, ChronoUnit.MONTHS);
list.add(isCurrent);
result+=isCurrent;
recency_num = isCurrent;
}
}
}
}
def min = list.get(0);
for (int i : list){
min = min < i ? min : i;
}
return min;
""",
"params": {
"search_keywords": "Machine Learning",
"current_datetime": current_milliseconds
}
}
}
}
}
Thanks in advance.
A valid script_score query in your case would look something like this:
GET my-index/_search
{
"query": {
"bool": {
"must": [
{
"function_score": {
"functions": [
{
"script_score": {
"script": {
"source": """
def myString = "";
def isCurrent = 0;
def isFound = false;
def index_position = 0;
def recency_num = 0;
def result = 0;
def list = new ArrayList();
def experiences = params._source.person.experiences;
// for loop starts here
for (int i=0; i<experiences.length; i++){
def experience = experiences[i];
myString = experience.description;
// string match starts here
if(myString != null && myString != '') {
def matcher1 = /electric/.matcher(myString.toLowerCase());
def matcher2 = /vehicle/.matcher(myString.toLowerCase());
if (matcher1.find() || matcher2.find()){
isFound = true;
}
if (isFound == true){
// recency check starts here
isCurrent = experience.isCurrent;
if (isCurrent == true){
isCurrent=0;
result += isCurrent;
list.add(isCurrent);
} else {
def now = ZonedDateTime.ofInstant(Instant.ofEpochMilli(params['current_datetime']), ZoneId.of('Z'));
def end_date = ZonedDateTime.parse(experience.end);
isCurrent = end_date.until(now, ChronoUnit.MONTHS);
list.add(isCurrent);
result += isCurrent;
recency_num = isCurrent;
}
}
}
}
if (list.length === 0) {
return 0;
}
def min = list.get(0);
for (int i : list){
min = min < i ? min : i;
}
return min;
""",
"params": {
"search_keywords": "Machine Learning",
"current_datetime": 1643036066000
}
}
}
}
]
}
}
]
}
}
}
Note that loads of regexes, iteration, and (date) parsing can drastically increase the query resolution.

Why I get a error 200 by websocket with python?

Code:
const WebSocket = require('ws');
const shaUtil = require('js-sha256');
String.prototype.hashCode = function() {
return shaUtil(String(this));
};
const server = new WebSocket.Server({port:2909}); // Change to another port if you like.
// Hashes of client keys. Generate them using getHash.js and place them here.
const passes = {
'86cec081a5288000ddb804c24ac70de62a5060e5b4f4068b01a01f9f29dddacc': 0, // Receiver's key.
'c01223ad2ba8cdd184ded788cf6d3469111229cbe6cb3939ce24f471e8f257ca': 1, // Buzzer #1's key.
'5476be1700a54be0572b0066b32b5905986641fa163c5eabd52369eb3a2685cf': 2 // Buzzer #2's key...
};
var receiver = null;
var senders = {1: null, 2: null, 3: null, 4: null}; // You can add more/remove buzzers if you want to.
const lockClients = true; // If it is true, a connected client will not be overriden by another client logging in until it disconnects.
if (lockClients) canConnect = function(id) {
if (id == 0) return receiver === null;
return senders[id] === null;
}
else canConnect = function(id) {
return true;
}
function processBuzzer(client) {
if (receiver == null) return;
receiver.send('BUZZER '+client.buzzerId);
//console.log('Buzzer #'+client.buzzerId+' is activated.');
}
function onDisconnect(id) {
if (id === 0) {
receiver = null;
console.log('Receiver has disconnected.');
} else {
senders[id] = null;
console.log('Sender #' + id + ' has disconnected.');
}
}
server.on('connection', function(client) {
client.sendBuzzer = function() {};
client.on('message', function(message) {
if (message.startsWith('PASSWORD: ')) {
let id = passes[message.substring(10).hashCode()];
if (id !== undefined && canConnect(id)) {
if (client.buzzerId !== undefined) onDisconnect(client.buzzerId);
client.buzzerId = id;
if (id === 0) {
receiver = client;
console.log('Receiver has connected.');
} else {
senders[id] = client;
console.log('Sender #' + id + ' has connected.');
client.sendBuzzer = function() { processBuzzer(this) };
client.send('CONNECTED SUCCESSFULLY');
}
}
}
if (message == 'BUZZER') client.sendBuzzer();
});
client.on('close', function() {
if (client.buzzerId !== undefined) onDisconnect(client.buzzerId);
});
});
console.log('Server is running.');
If i started this with nodeJS with "node server.js", it appears Server is running.....no mistakes.....and now, Iwill connect to this server with the receiver.py (Python-File):
serverAddress = 'ws://192.168.1.50:2909' # The server's address.
clientKey = 'receiver' # The client key corresponding to the receiver's hash.
buzzerSoundFile = 'buzzer.wav' # The name/path of the buzzer sound file.
import asyncio
import websockets
from win32com.client import Dispatch
import winsound
from threading import Thread
app = Dispatch('Powerpoint.Application')
def playBuzzerSound():
global buzzerSoundFile
winsound.PlaySound(buzzerSoundFile, winsound.SND_FILENAME+winsound.SND_ASYNC)
async def mainFunction():
global serverAddress, clientKey
async with websockets.connect(serverAddress) as ws:
await ws.send('PASSWORD: ' + clientKey)
while True:
msg = await ws.recv()
if msg.startswith('BUZZER '):
if app.Run('onBuzzerActivated', int(msg[7:])):
Thread(target=playBuzzerSound).start();
asyncio.get_event_loop().run_until_complete(mainFunction())
I got an error 200 like this:
websockets.exceptions.InvalidStatusCode: server rejected WebSocket connection: HTTP 200
What's wrong ??

How to convert C# password hashing with salt to python for windows

How to convert below code in Python so that it gives same value on Windows even when executed multiple times.
Basically, it hashing password using sha512 and salt with 1000 iterations.
Here is the code:
using System;
using System.Security.Cryptography;
using System.Text;
namespace CheckHashing
{
class Program
{
protected static string CreateSHA512Hash(string Password, string Salt)
{
try
{
byte[] bytes_password = Encoding.UTF8.GetBytes(Password);
byte[] bytes_salt = Encoding.UTF8.GetBytes(Salt);
HashAlgorithm sha512hash = (HashAlgorithm)new SHA512CryptoServiceProvider();
for (int index = 0; index < 1000; ++index)
{
byte[] bytes_iteration = Encoding.UTF8.GetBytes(Convert.ToBase64String(bytes_password) + Convert.ToBase64String(bytes_salt));
bytes_password = sha512hash.ComputeHash(bytes_iteration);
}
return Convert.ToBase64String(bytes_password);
}
catch (Exception ex)
{
return "Exception"+ex.Message;
}
}
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
string hash_pwd = CreateSHA512Hash("Pass#21", "SALT(}");
Console.WriteLine(hash_pwd);
// Answer => HoCg9kKAl5WY0lWzvH7hdW+cTQGUfknALKDw49rvzUVUTt9X9fuggGpDIRfCdotR/kVU8m7gj2xzRzwIfDc5Xw==
}
}
}
Already tried below code which gives different values. Below output gives Invalid Password as error in the function.
import hashlib
from base64 import b64encode
password = "Pass#21"
salt = "SALT(}"
h = hashlib.pbkdf2_hmac('sha512', password.encode('utf-8'), salt.encode('utf-8'), 1000)
print(b64encode(h).decode())
# and below as well
hex_hash = hashlib.sha512(password.encode('utf-8') + salt.encode('utf-8')).digest()
for i in range(1000):
hex_hash = hashlib.sha512(hex_hash + salt.encode('utf-8')).digest()
print(b64encode(hex_hash).decode())
from passlib.hash import sha512_crypt as sha512
sha512_passwd = sha512.hash(password, rounds=1000)
print(sha512_passwd)
They don't start out the same.
If you add some prints to the C#
protected static string CreateSHA512Hash(string Password, string Salt)
{
try
{
byte[] bytes_password = Encoding.UTF8.GetBytes(Password);
byte[] bytes_salt = Encoding.UTF8.GetBytes(Salt);
HashAlgorithm sha512hash = (HashAlgorithm)new SHA512CryptoServiceProvider();
for (int index = 0; index < 1000; ++index)
{
if (index < 10)
Console.WriteLine(Convert.ToBase64String(bytes_password));
byte[] bytes_iteration = Encoding.UTF8.GetBytes(Convert.ToBase64String(bytes_password) + Convert.ToBase64String(bytes_salt));
bytes_password = sha512hash.ComputeHash(bytes_iteration);
}
Console.WriteLine("...");
return Convert.ToBase64String(bytes_password);
}
catch (Exception ex)
{
return "Exception" + ex.Message;
}
}
Here's my python port of the same code, with the same debug prints, so you can compare the first 10 values.
import hashlib
from base64 import b64encode
password = "Pass#21"
salt = "SALT(}"
bytes_password = password.encode('utf-8')
bytes_salt = salt.encode('utf-8')
for i in range(1000):
if i < 10:
print(b64encode(bytes_password).decode())
b64pw = b64encode(bytes_password).decode()
b64sa = b64encode(bytes_salt).decode()
bytes_iteration = (b64pw + b64sa).encode('utf-8')
bytes_password = hashlib.sha512(bytes_iteration).digest()
print('...')
print(b64encode(bytes_password).decode())
Your original code wasn't consistent on when it hex encoded and when it computed the hash, and it computed a hash prior to entering the loop.

Is there a Python equivalent to these functions?

This code coverts an Array Buffer to a String and vice versa
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}
function str2ab(str) {
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
I think Python bytearray() can do the job.
u can refer this page for more info: https://www.programiz.com/python-programming/methods/built-in/bytearray

Categories

Resources