[Tkabber-dev] r2058 - in trunk/tkabber-plugins: . otr/tclotr

tkabber-svn at jabber.ru tkabber-svn at jabber.ru
Sat Jan 18 00:19:59 MSK 2014


Author: sergei
Date: 2014-01-18 00:19:59 +0400 (Sat, 18 Jan 2014)
New Revision: 2058

Modified:
   trunk/tkabber-plugins/ChangeLog
   trunk/tkabber-plugins/otr/tclotr/crypto.tcl
   trunk/tkabber-plugins/otr/tclotr/otr.tcl
   trunk/tkabber-plugins/otr/tclotr/smp.tcl
Log:
	* otr/tclotr/crypto.tcl: Added procedure which computes binary
	  DSA public key fingerprint.

	* otr/tclotr/otr.tcl: Don't compute DSA key fingerprint directly, but convert
	  the one computed in the otr::crypto package.

	* otr/tclotr/smp.tcl: Initially implemented parsing, creating and verifying
	  OTR SMP messages.


Modified: trunk/tkabber-plugins/ChangeLog
===================================================================
--- trunk/tkabber-plugins/ChangeLog	2014-01-17 15:44:22 UTC (rev 2057)
+++ trunk/tkabber-plugins/ChangeLog	2014-01-17 20:19:59 UTC (rev 2058)
@@ -6,6 +6,15 @@
 
 	* debug/debug.tcl: Added the otr debug category.
 
+	* otr/tclotr/crypto.tcl: Added procedure which computes binary
+	  DSA public key fingerprint.
+
+	* otr/tclotr/otr.tcl: Don't compute DSA key fingerprint directly, but convert
+	  the one computed in the otr::crypto package.
+
+	* otr/tclotr/smp.tcl: Initially implemented parsing, creating and verifying
+	  OTR SMP messages.
+
 2014-01-01  Sergei Golovan <sgolovan at nes.ru>
 
 	* *: 1.0 is released.

Modified: trunk/tkabber-plugins/otr/tclotr/crypto.tcl
===================================================================
--- trunk/tkabber-plugins/otr/tclotr/crypto.tcl	2014-01-17 15:44:22 UTC (rev 2057)
+++ trunk/tkabber-plugins/otr/tclotr/crypto.tcl	2014-01-17 20:19:59 UTC (rev 2058)
@@ -170,6 +170,24 @@
 #
 #       DSA signing and verifying
 
+# ::otr::crypto::DSAFingerprint --
+#
+#       Return the DSA public key fingerprint.
+#
+# Arguments:
+#       key         DSA public key {p q g y}.
+#
+# Result:
+#       The binary SHA-1 hash of the binary representation of the key.
+#
+# Side effects:
+#       None.
+
+proc ::otr::crypto::DSAFingerprint {key} {
+    set bytes [::otr::data::encode PUBKEY $key]
+    return [::sha1::sha1 -bin [string range $bytes 2 end]]
+}
+
 # ::otr::crypto::sign --
 #
 #       Sign binary data using the DSA algorithm.

Modified: trunk/tkabber-plugins/otr/tclotr/otr.tcl
===================================================================
--- trunk/tkabber-plugins/otr/tclotr/otr.tcl	2014-01-17 15:44:22 UTC (rev 2057)
+++ trunk/tkabber-plugins/otr/tclotr/otr.tcl	2014-01-17 20:19:59 UTC (rev 2058)
@@ -15,6 +15,7 @@
 package require otr::data
 package require otr::crypto
 package require otr::auth
+package require otr::smp
 package require otr::message
 
 package provide otr 0.1
@@ -812,14 +813,14 @@
 #       key         DSA public key {p q g y}.
 #
 # Result:
-#       The SHA-1 hash of the binary representation of the key.
+#       The hex SHA-1 hash of the binary representation of the key.
 #
 # Side effects:
 #       None.
 
 proc ::otr::fingerprint {key} {
-    set bytes [::otr::data::encode PUBKEY $key]
-    return [::sha1::sha1 -hex [string range $bytes 2 end]]
+    binary scan [::otr::crypto::DSAFingerprint $key] H* res
+    set res
 }
 
 # ::otr::Debug --

Modified: trunk/tkabber-plugins/otr/tclotr/smp.tcl
===================================================================
--- trunk/tkabber-plugins/otr/tclotr/smp.tcl	2014-01-17 15:44:22 UTC (rev 2057)
+++ trunk/tkabber-plugins/otr/tclotr/smp.tcl	2014-01-17 20:19:59 UTC (rev 2058)
@@ -19,8 +19,313 @@
 
 ##############################################################################
 
-namespace eval ::otr::smp {}
+namespace eval ::otr::smp {
+    variable q [expr {($::otr::crypto::Prime-1)/2}]
+    variable g1 $::otr::crypto::G
+}
 
-# TODO
+# ::otr::smp::createSMPMessage1 --
 
+proc ::otr::smp::createSMPMessage1 {smpstate a2 a3 r2 r3 privkey pubkey gy dh usersecret} {
+    variable q
+    variable g1
+    set x [Secret $privkey $pubkey $gy $dh $usersecret]
+    set g2a [Exp $g1 $a2]
+    set g3a [Exp $g1 $a3]
+    set c2 [Hash 1 [Exp $g1 $r2]]
+    set D2 [expr {($r2-$a2*$c2) % $q}]
+    set c3 [Hash 2 [Exp $g1 $r3]]
+    set D3 [expr {($r3-$a3*$c3) % $q}]
+
+    list SMPSTATE_EXPECT2 2 [Payload $g2a $c2 $D2 $g3a $c3 $D3] $x $a2 $a3
+}
+
+# ::otr::smp::processSMPMessage1 --
+
+proc ::otr::smp::processSMPMessage1 {smpstate data b2 b3 r2 r3 r4 r5 r6 privkey pubkey gy dh usersecret} {
+    variable q
+    variable g1
+
+    switch -- $smpstate {
+        SMPSTATE_EXPECT1 {
+            if {[catch {ParsePayload $data} res]} {
+                puts "Parse of SMP message 1 failed"
+                return [list $smpstate 6 ""]
+            }
+
+            lassign $res g2a c2 D2 g3a c3 D3
+
+            if {![Check $g2a] || ![Check $g3a]} {
+                puts "Check 1 of SMP message 1 failed"
+                return [list $smpstate 6 ""]
+            }
+
+            set myc2 [Hash 1 [Mult [Exp $g1 $D2] [Exp $g2a $c2]]]
+            if {$myc2 != $c2} {
+                puts "Check 2 of SMP message 1 failed"
+                return [list $smpstate 6 ""]
+            }
+
+            set myc3 [Hash 2 [Mult [Exp $g1 $D3] [Exp $g3a $c3]]]
+            if {$myc3 != $c3} {
+                puts "Check 3 of SMP message 1 failed"
+                return [list $smpstate 6 ""]
+            }
+
+            set y [Secret $pubkey $privkey $gy $dh $usersecret]
+            set g2b [Exp $g1 $b2]
+            set g3b [Exp $g1 $b3]
+            set c2 [Hash 3 [Exp $g1 $r2]]
+            set D2 [expr {($r2-$b2*$c2) % $q}]
+            set c3 [Hash 4 [Exp $g1 $r3]]
+            set D3 [expr {($r3-$b3*$c3) % $q}]
+            set g2 [Exp $g2a $b2]
+            set g3 [Exp $g3a $b3]
+            set Pb [Exp $g3 $r4]
+            set Qb [Mult [Exp $g1 $r4] [Exp $g2 $y]]
+            set cP [Hash 5 [Exp $g3 $r5] [Mult [Exp $g1 $r5] [Exp $g2 $r6]]]
+            set D5 [expr {($r5-$r4*$cP) % $q}]
+            set D6 [expr {($r6-$y*$cP) % $q}]
+
+            return [list SMPSTATE_EXPECT3 3 \
+                         [Payload $g2b $c2 $D2 $g3b $c3 $D3 $Pb $Qb $cP $D5 $D6] \
+                         $g3a $g2 $g3 $b3 $Pb $Qb]
+        }
+        default {
+            # Abort SMP
+            return [list SMPSTATE_EXPECT1 6 ""]
+        }
+    }
+}
+
+# ::otr::smp::processSMPMessage2 --
+
+proc ::otr::smp::processSMPMessage2 {smpstate data r4 r5 r6 r7 x a2 a3} {
+    variable q
+    variable g1
+
+    switch -- $smpstate {
+        SMPSTATE_EXPECT2 {
+            if {[catch {ParsePayload $data} res]} {
+                puts "Parse of SMP message 2 failed"
+                return [list $smpstate 6 ""]
+            }
+
+            lassign $res g2b c2 D2 g3b c3 D3 Pb Qb cP D5 D6
+
+            if {![Check $g2b] || ![Check $g3b] ||
+                    ![Check $Pb] || ![Check $Qb]} {
+                puts "Check 1 of SMP message 2 failed"
+                return [list $smpstate 6 ""]
+            }
+
+            set myc2 [Hash 3 [Mult [Exp $g1 $D2] [Exp $g2b $c2]]]
+            if {$myc2 != $c2} {
+                puts "Check 2 of SMP message 2 failed"
+                return [list $smpstate 6 ""]
+            }
+
+            set myc3 [Hash 4 [Mult [Exp $g1 $D3] [Exp $g3b $c3]]]
+            if {$myc3 != $c3} {
+                puts "Check 3 of SMP message 2 failed"
+                return [list $smpstate 6 ""]
+            }
+
+            set g2 [Exp $g2b $a2]
+            set g3 [Exp $g3b $a3]
+            set mycP [Hash 5 [Mult [Exp $g3 $D5] [Exp $Pb $cP]] \
+                             [Mult [Exp $g1 $D5] \
+                                   [Mult [Exp $g2 $D6] [Exp $Qb $cP]]]]
+            if {$mycP != $cP} {
+                puts "Check 4 of SMP message 2 failed"
+                return [list $smpstate 6 ""]
+            }
+
+            set Pa [Exp $g3 $r4]
+            set Qa [Mult [Exp $g1 $r4] [Exp $g2 $x]]
+            set cP [Hash 6 [Exp $g3 $r5] [Mult [Exp $g1 $r5] [Exp $g2 $r6]]]
+            set D5 [expr {($r5-$r4*$cP) % $q}]
+            set D6 [expr {($r6-$x*$cP) % $q}]
+            set PaPb [Mult $Pa [Inv $Pb]]
+            set QaQb [Mult $Qa [Inv $Qb]]
+            set Ra [Exp $QaQb $a3]
+            set cR [Hash 7 [Exp $g1 $r7] [Exp $QaQb $r7]]
+            set D7 [expr {($r7-$a3*$cR) % $q}]
+
+            return [list SMPSTATE_EXPECT4 4 \
+                         [Payload $Pa $Qa $cP $D5 $D6 $Ra $cR $D7] \
+                         $g3b $PaPb $QaQb $Ra]
+        }
+        default {
+            # Abort SMP
+            return [list SMPSTATE_EXPECT1 6 ""]
+        }
+    }
+}
+
+# ::otr::smp::processSMPMessage3 --
+
+proc ::otr::smp::processSMPMessage3 {smpstate data r7 g3a g2 g3 b3 Pb Qb} {
+    variable q
+    variable g1
+
+    switch -- $smpstate {
+        SMPSTATE_EXPECT3 {
+            if {[catch {ParsePayload $data} res]} {
+                puts "Parse of SMP message 3 failed"
+                return [list $smpstate 6 ""]
+            }
+
+            lassign $res Pa Qa cP D5 D6 Ra cR D7
+
+            set QaQb [Mult $Qa [Inv $Qb]]
+
+            if {![Check $Pa] || ![Check $Qa] || ![Check $Ra]} {
+                puts "Check 1 of SMP message 3 failed"
+                return [list $smpstate 6 ""]
+            }
+
+            set mycP [Hash 6 [Mult [Exp $g3 $D5] [Exp $Pa $cP]] \
+                             [Mult [Exp $g1 $D5] \
+                                   [Mult [Exp $g2 $D6] [Exp $Qa $cP]]]]
+            if {$mycP != $cP} {
+                puts "Check 2 of SMP message 3 failed"
+                return [list $smpstate 6 ""]
+            }
+
+            set mycR [Hash 7 [Mult [Exp $g1 $D7] [Exp $g3a $cR]] \
+                             [Mult [Exp $QaQb $D7] [Exp $Ra $cR]]]
+            if {$mycR != $cR} {
+                puts "Check 3 of SMP message 3 failed"
+                return [list $smpstate 6 ""]
+            }
+
+            set Rb [Exp $QaQb $b3]
+            set cR [Hash 8 [Exp $g1 $r7] [Exp $QaQb $r7]]
+            set D7 [expr {($r7-$b3*$cR) % $q}]
+
+            set PaPb [Mult $Pa [Inv $Pb]]
+            set Rab [Exp $Ra $b3]
+            set res [expr {$PaPb == $Rab}]
+
+            return [list SMPSTATE_EXPECT1 5 \
+                         [Payload $Rb $cR $D7] \
+                         $res]
+        }
+        default {
+            # Abort SMP
+            return [list SMPSTATE_EXPECT1 6 ""]
+        }
+    }
+}
+
+# ::otr::smp::processSMPMessage4 --
+
+proc ::otr::smp::processSMPMessage4 {smpstate data a3 g3b PaPb QaQb Ra} {
+    variable q
+    variable g1
+
+    switch -- $smpstate {
+        SMPSTATE_EXPECT4 {
+            if {[catch {ParsePayload $data} res]} {
+                puts "Parse of SMP message 4 failed"
+                return [list $smpstate 6 ""]
+            }
+
+            lassign $res Rb cR D7
+
+            if {![Check $Rb]} {
+                puts "Check 1 of SMP message 4 failed"
+                return [list $smpstate 6 ""]
+            }
+
+            set mycR [Hash 8 [Mult [Exp $g1 $D7] [Exp $g3b $cR]] \
+                             [Mult [Exp $QaQb $D7] [Exp $Rb $cR]]]
+            if {$mycR != $cR} {
+                puts "Check 2 of SMP message 3 failed"
+                return [list $smpstate 6 ""]
+            }
+
+            set Rab [Exp $Rb $a3]
+            set res [expr {$PaPb == $Rab}]
+
+            return [list SMPSTATE_EXPECT1 0 "" $res]
+        }
+        default {
+            # Abort SMP
+            return [list SMPSTATE_EXPECT1 6 ""]
+        }
+    }
+}
+
+# ::otr::smp::Check --
+
+proc ::otr::smp::Check {a} {
+    ::otr::crypto::DHCheck $a
+}
+
+# ::otr::smp::Exp --
+
+proc ::otr::smp::Exp {a b} {
+    ::otr::crypto::DHSecret $a $b
+}
+
+proc ::otr::smp::Mult {a b} {
+    ::otr::crypto::Mult $::otr::crypto::Prime $a $b
+}
+
+# ::otr::smp::Inv --
+
+proc ::otr::smp::Inv {a} {
+    ::otr::crypto::Inverse $::otr::crypto::Prime $a
+}
+
+# ::otr::smp::ParsePayload --
+
+proc ::otr::smp::ParsePayload {data} {
+    set res {}
+    lassign [::otr::data::decode INT $data] count data
+    for {set i 0} {$i < $count} {incr i} {
+        lassign [::otr::data::decode MPI $data] num data
+        lappend res $num
+    }
+    set res
+}
+
+# ::otr::smp::Payload --
+
+proc ::otr::smp::Payload {args} {
+    set res ""
+    append res [::otr::data::encode INT [llength $args]]
+    foreach num $args {
+        append res [::otr::data::encode MPI $num]
+    }
+    set res
+}
+
+# ::otr::smp::Hash --
+
+proc ::otr::smp::Hash {version arg1 {arg2 ""}} {
+    set res ""
+    append res [::otr::data::encode BYTE $version]
+    append res [::otr::data::encode MPI $arg1]
+    if {$arg2 ne ""} {
+        append res [::otr::data::encode MPI $arg2]
+    }
+    ::otr::crypto::Bits2Int [::sha2::sha256 -bin $res]
+}
+
+# ::otr::smp::Secret --
+
+proc ::otr::smp::Secret {pubkey1 pubkey2 gy x secret} {
+    set res ""
+    append res [::otr::data::encode BYTE 1]
+    append res [::otr::crypto::DSAFingerprint $pubkey1]
+    append res [::otr::crypto::DSAFingerprint $pubkey2]
+    lassign [::otr::crypto::DHKeys $gy $x] ssid
+    append res $ssid
+    append res [encoding convertto utf-8 $secret]
+    ::otr::crypto::Bits2Int [::sha2::sha256 -bin $res]
+}
+
 # vim:ts=8:sw=4:sts=4:et



More information about the Tkabber-dev mailing list