Syria1993
Anmeldungsdatum: 5. September 2016
Beiträge: 9
|
Hallo Gemeinde, | root@beaglebone:~/ENCRYPTION# cat /proc/version
Linux version 4.4.9-ti-r25 (root@b3-jetson-tk1-2gb) (gcc version 4.9.2 (Debian 4.9.2-10) ) #1 SMP Thu May 5 23:08:13 UTC 2016
|
Ich habe mir kürzlich einen BeagleboneBlack zugelegt, der über CAN mit einem zweiten kommuniziert. Hier möchte ich eine Verschlüsselung implementieren. Kann mir jemand demonstrieren wie eine Zeichenkette in Shell verschlüsselt werden kann? Dazu möchte ich keine Zwischendatei benutzen und das Ganze sollte möglichst schnell funktionieren, da CAN eine Echtzeitanforderung hat. So wäre auch eine symmetrische Verschlüsselung angebracht. Ich würde zum Beispiel gerne das übergebene Argument $1="ABCD" einmal überprüfen lassen ob es eine hexadezimale Zahl zwischen 0x00000000 und 0x1FFFFFFF ist und anschließend diese Daten mit einem Algorithmus verschlüsseln und direkt an ein Kommando übergeben. Hat jemand eine Idee wie so eine Verschlüsselung von Zahlen möglich ist? Ich stelle mir das wie folgt vor:
| root@beaglebone:./encryption ABCD
echo $1 # Ausgabe: 'ABCD'
FKT_HEX($1) # Mit Ausgabe auf True oder False
FKT_ENCRYPTION($1)
echo "$1" # Ausgabe '12ae4c51cae1ea5191661ac152ca25ca23'
|
Perfekt würde das Ganze sein, wenn ich selbst Schlüssel zur Verschlüsselung generieren könnte. Danke Vorab! Gruß
Syria1993
|
misterunknown
Ehemalige
Anmeldungsdatum: 28. Oktober 2009
Beiträge: 4403
Wohnort: Sachsen
|
Nutze einfach openssl:
echo "Das wird ein verschlüsselter Text" | openssl enc -aes-256-cbc -a
Du kannst natürlich viele verschiedene Verschlüsselungsarten verwenden. Welche Ciphers von deinem System unterstützt werden, siehst du in der Manpage:
man enc
|
Syria1993
(Themenstarter)
Anmeldungsdatum: 5. September 2016
Beiträge: 9
|
@ misterunknown: Danke für die schnelle Antwort. Das ist genau das was ich gesucht habe! Einen Haken habe ich jedoch noch nicht gelöst was die Kodierung angeht. Mit: | openssl genrsa -out private_key.pem 1024
|
Erstelle ich einen Schlüssel. Mit: | echo "ABCD" | openssl rsautl -encrypt -inkey private_key.pem
|
bekomme ich lauter kryptische Zeichen als Ausgabe die ich noch in hexadezimale Zeichen umkodieren muss, da über CAN nur in acht Byte Schritten HEX gesendet werden kann. Eine Idee wie dies "on the fly" machbar ist?
|
track
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
Wohnort: Wolfen (S-A)
|
Hi Syria1993, zuerst mal herzlich willkommen hier auf dem Forum ! Syria1993 schrieb: ... Ausgabe die ich noch in hexadezimale Zeichen umkodieren muss, da über CAN nur in acht Byte Schritten HEX gesendet werden kann. Eine Idee wie dies "on the fly" machbar ist?
Klingt irgendwie komisch: brauchst Du nun HEX- codierte Zeichen, oder brauchst Du 8-er-Gruppen, oder was genau ? - das müsstest Du nochmal genauer sagen. Sonst würde ich ja normalerweise an base64 denken. das wirft immer 4-Byte-Gruppen aus, und verwendet im Prinzip nur Zahlen und Buchstaben. LG, track
|
Syria1993
(Themenstarter)
Anmeldungsdatum: 5. September 2016
Beiträge: 9
|
zuerst mal herzlich willkommen hier auf dem Forum !
Hallo Track, danke für den Willkommensgruß. Ich versuche dir das möglichst kurz und knackig zu erklären. Die CAN Spezifikation kann nur 8 Byte Nutzdaten pro Frame in HEX-Notation versenden. Beispiel für den SocketCAN-Linux Befehl: | cansend can0 123#AABBCCDDEEFF1122 # CAN-ID= 123 und AABBCCDDEEFF1122 sind die Nutzdaten in HEX
|
Nun möchte ich aber beispielsweise die Daten 'AABBCCDDEEFF1122' verschlüsseln: | echo "AABBCCDDEEFF1122" | openssl rsautl -encrypt -inkey private_key.pem
|
und da kommen natürlich lauter kryptischer Zeichen raus, die ich nicht mit dem Befehl 'candsend' versenden kann. Ich hatte die Idee dies über 'hexdump' zu lösen aber da weiß ich nicht wie ich die HEX-Zeichen am anderen Ende in die ursprüngliche Nachricht zusammensetzen kann.
|
senden9
Anmeldungsdatum: 8. Februar 2010
Beiträge: 965
Wohnort: Österreich
|
Hi. Zwar keine direkte Antwort aber ein Denkanstoß Schon mal daran gedacht eine „richtige“ Programmiersprache wie Python oder C++ zu verwenden?
Zumindest wenn es etwas aufwendiger werden soll würde ich dir das empfehlen. Hier gibt es ein nicht so gut dokumentiertes Beispiel in Python zur Kommunikation mit CAN. Um das zu verstehen sollte man sich die Dokumentation zum Socketmodul durchlesen. Für die Verschlüsselung gibt es auch ein einfaches Beispiel.
|
Syria1993
(Themenstarter)
Anmeldungsdatum: 5. September 2016
Beiträge: 9
|
Hallo senden9, Ich habe wirklich schon überlegt das Ganze in C++ zu schreiben. Jedoch bin ich nicht tief in der Programmierung drin. Ich wüsste z.B nicht wie ich Bashcommandos und dessen Ausgaben in C implementieren kann. Deswegen habe ich Bash gewählt. Übrigens habe ich eine Lösung für mein Problem gefunden. Mit 'xxd' klappt es scheinbar: 1
2
3
4
5
6
7
8
9
10
11
12
13 | # Verschlüssen und in HEX
root@beaglebone:~/ENCRYPTION# echo "ABCD" | openssl rsautl -encrypt -inkey private_key.pem | xxd
0000000: 3359 c4eb acd6 8d58 2f94 e9fb 4852 2a69 3Y.....X/...HR*i
0000010: f8f9 e6f3 71f1 1ef4 b273 f301 afb3 4ca4 ....q....s....L.
0000020: 3b0c 9b37 de06 eb3d 61f4 0f85 db91 edfc ;..7...=a.......
0000030: e77b 1b8d 7bc9 2480 b2ca 7a49 9300 297c .{..{.$...zI..)|
0000040: b5ad 9510 59b2 c0b3 8eb2 152e 5278 e70a ....Y.......Rx..
0000050: 5306 e1ff bf2c db74 0ee2 5103 a983 c330 S....,.t..Q....0
0000060: 9d84 35d6 84eb 6833 eeb1 4c39 333d 8d05 ..5...h3..L93=..
0000070: a824 ac50 5d88 aa68 df01 a118 12fc 8996 .$.P]..h........
# Reverse HEX und entschlüsseln
echo "ABCD" | openssl rsautl -encrypt -inkey private_key.pem | xxd | xxd -r | openssl rsautl -decrypt -inkey private_key.pem
ABCD
|
Das was jetzt kommt wäre in C vermutlich am einfachsten zu realisieren und wsh. für meine Echtzeitanforderung sehr nützlich. Doch wie gesagt, ich müsste mich ewig einarbeiten. Jetzt muss ich mir nurnoch mein Protokoll selbst zusammenbasteln und den Output von 'xxd' häppchenweise in 8-Byte-Schritten auf den CAN purzeln lassen. Dann sollte die Arbeit getan sein.
|
track
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
Wohnort: Wolfen (S-A)
|
Ich weiß ja nicht, was für Einschränkungen Deine Geräte evt. haben, aber von der Sache her verträgt das CAN-Protokoll ja eigentlich "0 bis 8 Byte" im Datenfeld. Deshalb würde ich da eher kein Problem erwarten. (und auch bezüglich des Dateninhalts sehe ich eigentlich keine Notwendigkeit für HEX) Aber gut, wenn Du es unbedingt so haben willst, geht das natürlich auch. Du musst es dem hexdump dann eben als Formatierung mitgeben. (so etwas ähnliches hatte wir die Tage hier schon mal - wie das genau geht, müsstest Du Dir mal in man hexdump heraus suchen) LG, track
|
Syria1993
(Themenstarter)
Anmeldungsdatum: 5. September 2016
Beiträge: 9
|
Ich habe mich nach etwas Übelegen doch dem Ansatz mit Python gewidmet. Derzeit sieht mein Code wie folgt aus: Aufruf: python3 can0 111 DEADBEEF 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 |
import socket
import struct
import sys
import binascii
# CAN frame packing/unpacking (see `struct can_frame` in <linux/can.h>)
can_frame_fmt = "=IB3x8s"
# Defines
def build_can_frame(can_id, data):
can_dlc = len(data)
data = data.ljust(8, b'\x00')
return struct.pack(can_frame_fmt, can_id, can_dlc, data)
def dissect_can_frame(frame):
can_id, can_dlc, data = struct.unpack(can_frame_fmt, frame)
return (can_id, can_dlc, data[:can_dlc])
# Check of arguments
if len(sys.argv) != 4:
print('Type of arguments shall be: argv[0]=scriptname.py argv[1]=CAN-IF argv[2]=CAN-ID argv[3]')
print('Example: ./enc.py can0 123 DEADBEEF')
sys.exit(0)
# create a raw socket and bind it to the given CAN interface
s = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW)
s.bind((sys.argv[1],))
#Testausgabe 01
print ( build_can_frame(int(sys.argv[2],16), b'\xAA\x02\xFF') )
# Receive Data and Send when something received
while True:
cf, addr= s.recvfrom(16)
print('Rx: CAN_ID=%x [%x] %s' % dissect_can_frame(cf))
try:
s.send(cf)
print (cf)
except socket.error:
print('Error sending CAN frame back')
try:
s.send(build_can_frame(int(sys.argv[2],16), b'\xAA\x02\xFF'))
except socket.error:
print('Error sending CAN frame')
|
Mein Ziel ist es, dass Hexzahlen, die als Argument an argv3 übergeben werden, auch als Daten anstelle von | b'\xAA\x02\xFF' # in s.send(build_can_frame(int(sys.argv[2],16), b'\xAA\x02\xFF'))
|
versendet werden können. Doch verstehe ich den Zusammenhang von b'\xAA\x02\xFF' und 'data = data.ljust(8, b'\x00')' nicht und wie ich da meine Daten von argv3 "einschleusen" kann. Am Ende soll etwas wie die Ausgabe von print ( build_can_frame(int(sys.argv[2],16), b'\xAA\x02\xFF') ) in Zeile 33 rauskommen:
| print ( build_can_frame(int(sys.argv[2],16), b'\xAA\x02\xFF') )
# Ausgabe: b'D\x04\x00\x00\x01\x00\x00\x00\x11\xff\x00\x00\x00\x00\x00\x00'
|
Wie man sieht ist die Kodierung dahinter hoch merkwürdig. Ich versuche lediglich meine Daten aus argv3 als data zu versenden. Hat wer eine Idee?
|
senden9
Anmeldungsdatum: 8. Februar 2010
Beiträge: 965
Wohnort: Österreich
|
Syria1993 schrieb: […] Doch verstehe ich den Zusammenhang von b'\xAA\x02\xFF' und 'data = data.ljust(8, b'\x00')' nicht […]
Laut Dokumentation sorgt ljust(8, b'\x00') dafür das deine Daten Vielfache von 8 Byte lang sind. Sind sie kürzer werden sie von rechts mit Nullen aufgefüllt.
[…] wie ich da meine Daten von argv3 "einschleusen" kann. […]
Falls das umwandeln ein Problem darstellt könntest du dir fromhex ansehen. Das sollte dann ca so laufen:
| tx = bytearray.fromhex(sys.argv[3])
build_can_frame(int(sys.argv[2],16), tx)
|
|
Syria1993
(Themenstarter)
Anmeldungsdatum: 5. September 2016
Beiträge: 9
|
| tx = bytearray.fromhex(argv[0])
build_can_frame(int("aba",16), tx)
|
@senden9:
Ich liebe dich sowas von ungemein. Genau das was ich gesucht hatte! Damit hast du mir viele Stunden arbeit erspart. Danke. 👍
|
senden9
Anmeldungsdatum: 8. Februar 2010
Beiträge: 965
Wohnort: Österreich
|
|
Syria1993
(Themenstarter)
Anmeldungsdatum: 5. September 2016
Beiträge: 9
|
Hallo, ihr habt mir schon super gut geholfen und ich versuche es deswegen nochmal. Nach der Verschlüsselung kommen haufenweise kryptische Zeichen heraus. Hier ein Beispiel: | bKa9f1xh54HJzWK3MOW7Cu6LN6USPW+b2hvAUS0G4JOqwzgRZyvPAUtkVozuM45v
|
Wie kann dies möglichst effizient in eine HEX Codierung gebracht werden? Ich habe bisher nur die Befehle 'ord()' und 'chr' gefunden. Damit lassen sich jedoch nur Character umkodieren. Hier müssten aufwendige Schritte durchgeführt werden, um einen großen String in die Form: | b'D\x04\x00\x00\x01\x00\x00\x00\x11\xff\x00\x00\x00\x00\x00\x00'
|
zu bringen. Habt ihr Erfahrung mit Funktionen, die ganze Strings schnell in HEX-Zeichen konvertieren können und auch wieder zurück? Mein bisheriger Ansatz war mit binascii.hexlify: | H= binascii.hexlify(b"STRING")
print ("Encoded:", H)
#H = bytearray.fromhex(H)
print ("Fromhex:", H)
#H= binascii.unhexlify(H)
print ("Decoded:", H)
#TypeError: must be str, not bytes
|
Probleme:
Formatierter Text. Ich kann mit der Funktion hexlify keine Variable mit binascii.hexlify(A) mit A="String" aufrufen Sollte es Klappen kann ich den resultierenden String nicht mit bytearray.fromhex() weiterverarbeiten, weil es scheinbar kein String ist. Das ganze muss sich natürlich wieder dekodieren lassen
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13075
|
Syria1993 schrieb:
Wie kann dies möglichst effizient in eine HEX Codierung gebracht werden?
Mit Shell-Mitteln geht es so: | $ echo 'irgendein binaermuell' | od -An -w8 -t x1 -v | sed 's# \+##g'
697267656e646569
6e2062696e616572
6d75656c6c0a
$ for data in $(echo 'irgendein binaermuell' | od -An -w8 -t x1 -v | sed 's# \+##g'); do echo cansend can0 "123#$data"; done
cansend can0 123#697267656e646569
cansend can0 123#6e2062696e616572
cansend can0 123#6d75656c6c0a
|
Das echo in der Schleife muss dann natürlich raus. Und das andere durch den korrekten Input ersetzt. Ggf. möchtest Du noch tr a-h A-H dazwischen schalten um Großbuchstaben zu bekommen.
|
Syria1993
(Themenstarter)
Anmeldungsdatum: 5. September 2016
Beiträge: 9
|
Mit Shell-Mitteln geht es so:
Danke für deine Antwort. Ich werde mir den Ansatz im Hinterkopf halten aber versuche momentan eine Lösung mit python zu finden. Hast du eine Idee? Ich habe es mit der Funktion bytearray.fromhex() versucht aber da spielt mir Python einen Streich... schaut mal: | print ("1. fromhex('DEADBEEF'):", bytearray.fromhex("DEADBEEF") )
#1. fromhex('DEADBEEF'): bytearray(b'\xde\xad\xbe\xef')
print ("2. Fromhex('537472696e67'):", bytearray.fromhex("537472696e67"))
#2. Fromhex('537472696e67'): bytearray(b'String')
print ("3. Fromhex('0123456789ABCDEF'):", bytearray.fromhex("0123456789ABCDEF"))
#3. Fromhex('0123456789ABCDEF'): bytearray(b'\x01#Eg\x89\xab\xcd\xef')
|
Es ist abhängig vom String, was die Funktion übersetzt.... 'DEADBEEF' wird genau so übersetzt wie benötigt aber die Folge '537472696e67' wird in den String übersetzt... Wer da eine Idee hat 👿 Ich benötige das Format aus #1 und #3 aber die Daten müssen ja auch mit #2 Funktionieren. Datentypen sind alle gleich aber liefern andere Ergebnisse.
|