From: Michael Gernoth Date: Sun, 2 Jun 2013 09:46:13 +0000 (+0200) Subject: HMLAN AES-CFB implementation X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/fhem-stuff/commitdiff_plain/7836eda2dea521f15eb59b08e940719790c74349?ds=sidebyside HMLAN AES-CFB implementation --- diff --git a/HMLAN/HMLAN_CRYPT.pm b/HMLAN/HMLAN_CRYPT.pm new file mode 100644 index 0000000..12604b1 --- /dev/null +++ b/HMLAN/HMLAN_CRYPT.pm @@ -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 index 0000000..e80bf6f --- /dev/null +++ b/HMLAN/hmlan-crypt-test.pl @@ -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); + } + } +}