]> git.zerfleddert.de Git - fhem-stuff/commitdiff
HMLAN AES-CFB implementation
authorMichael Gernoth <michael@gernoth.net>
Sun, 2 Jun 2013 09:46:13 +0000 (11:46 +0200)
committerMichael Gernoth <michael@gernoth.net>
Sun, 2 Jun 2013 09:46:13 +0000 (11:46 +0200)
HMLAN/HMLAN_CRYPT.pm [new file with mode: 0644]
HMLAN/hmlan-crypt-test.pl [new file with mode: 0755]

diff --git a/HMLAN/HMLAN_CRYPT.pm b/HMLAN/HMLAN_CRYPT.pm
new file mode 100644 (file)
index 0000000..12604b1
--- /dev/null
@@ -0,0 +1,86 @@
+package HMLAN_CRYPT;
+
+use Crypt::Rijndael;
+
+sub decrypt(@)
+{
+       my ($self, $ciphertext) = @_;
+       my $plaintext = '';
+
+       while($ciphertext) {
+               if($self->{'keystream'}) {
+                       my $len;
+
+                       if (length($self->{'keystream'}) > length($ciphertext)) {
+                               $len = length($ciphertext);
+                       } else {
+                               $len = length($self->{'keystream'});
+                       }
+
+                       my $cpart = substr($ciphertext, 0, $len);
+                       my $kpart = substr($self->{'keystream'}, 0, $len);
+
+                       $ciphertext = substr($ciphertext, $len);
+                       $self->{'keystream'} = substr($self->{'keystream'}, $len);
+
+                       $self->{'ciphertext'} .= $cpart;
+
+                       $plaintext .= $cpart ^ $kpart;
+               } else {
+                       $self->{'keystream'} = $self->{'cipher'}->encrypt($self->{'ciphertext'});
+                       $self->{'ciphertext'}='';
+               }
+       }
+
+       $plaintext;
+}
+
+sub encrypt(@)
+{
+       my ($self, $plaintext) = @_;
+       my $ciphertext = '';
+
+       while($plaintext) {
+               if($self->{'keystream'}) {
+                       my $len;
+
+                       if (length($self->{'keystream'}) > length($plaintext)) {
+                               $len = length($plaintext);
+                       } else {
+                               $len = length($self->{'keystream'});
+                       }
+
+                       my $ppart = substr($plaintext, 0, $len);
+                       my $kpart = substr($self->{'keystream'}, 0, $len);
+
+                       $plaintext = substr($plaintext, $len);
+                       $self->{'keystream'} = substr($self->{'keystream'}, $len);
+
+                       $self->{'ciphertext'} .= $ppart ^ $kpart;
+
+                       $ciphertext .= $ppart ^ $kpart;
+               } else {
+                       $self->{'keystream'} = $self->{'cipher'}->encrypt($self->{'ciphertext'});
+                       $self->{'ciphertext'}='';
+               }
+       }
+
+       $ciphertext;
+}
+
+sub new
+{
+       my $class = shift;
+       my $key = shift;
+       my $iv = shift;
+
+       my $self = {
+               cipher          => Crypt::Rijndael->new($key, Crypt::Rijndael::MODE_ECB()),
+               keystream       => '',
+               ciphertext      => $iv,
+       };
+
+       bless $self, $class;
+}
+
+1;
diff --git a/HMLAN/hmlan-crypt-test.pl b/HMLAN/hmlan-crypt-test.pl
new file mode 100755 (executable)
index 0000000..e80bf6f
--- /dev/null
@@ -0,0 +1,59 @@
+#!/usr/bin/perl -w
+
+my $key="RUTYOURSECRETHMLANSTICKERKEYHERE";
+my $hmlan="192.168.1.2";
+
+BEGIN {
+       use File::Basename;
+       push @INC, dirname($0);
+}
+
+use HMLAN_CRYPT;
+use IO::Socket::INET;
+use IO::Select;
+
+#This should be random...
+my $my_iv = '00112233445566778899AABBCCDDEEFF';
+my $hmlan_iv = '';
+
+my $sock = IO::Socket::INET->new(
+       PeerAddr => $hmlan,
+       PeerPort => 1000,
+       Proto => 'tcp',
+       Blocking => 0);
+
+my $read_set = new IO::Select();
+$read_set->add($sock);
+
+$read_set->can_read();
+
+chomp(my $iv = <$sock>);
+if ($iv =~ /^V(................................)\r$/) {
+       $hmlan_iv = $1;
+} else {
+       print STDERR "Unknown IV received: ${iv}\n";
+       exit(1);
+}
+
+print $sock "V${my_iv}\r\n";
+
+my $cipher_hmlan=HMLAN_CRYPT->new(pack("H*", $key), pack("H*", $my_iv));
+my $cipher_pc=HMLAN_CRYPT->new(pack("H*", $key), pack("H*", $hmlan_iv));
+
+$read_set->add(\*STDIN);
+
+while(1) {
+       my @ready = $read_set->can_read();
+       foreach my $r (@ready) {
+               if ($r == $sock) {
+                       while(my $buf=<$r>) {
+                               print $cipher_hmlan->decrypt($buf);
+                       }
+               } else {
+                       my $buf = <$r>;
+                       exit(1) if (!$buf);
+
+                       print $sock $cipher_pc->encrypt($buf);
+               }
+       }
+}
Impressum, Datenschutz