This Riverbed TrafficScript library implements the HMAC/SHA1 and HMAC/MD5 calculations.
For more details and usage instructions, check out https://splash.riverbed.com/docs/DOC-1610
Tags: #Stingray #TrafficScript #HMAC #splash.riverbed.com
This Riverbed TrafficScript library implements the HMAC/SHA1 and HMAC/MD5 calculations.
For more details and usage instructions, check out https://splash.riverbed.com/docs/DOC-1610
Tags: #Stingray #TrafficScript #HMAC #splash.riverbed.com
# Riverbed TrafficScript HMAC library | |
# | |
# Function exports: | |
# MD5( key, data ) | |
# SHA1( key, data ) | |
sub MD5( $key, $data ) { | |
$blocksize = 64; # MD5 blocksize | |
$s00_64 = | |
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" . | |
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" . | |
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" . | |
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; | |
$s5c_64 = | |
"\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c" . | |
"\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c" . | |
"\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c" . | |
"\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c"; | |
$s36_64 = | |
"\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36" . | |
"\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36" . | |
"\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36" . | |
"\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36"; | |
if( string.length( $key ) > $blocksize ) $key = string.hashMD5( $key ); | |
if( string.length( $key ) < $blocksize ) $key = string.replaceBytes( $s00_64, $key, 0 ); | |
$o_key_pad = string_xor( $s5c_64, $key ); | |
$i_key_pad = string_xor( $s36_64, $key ); | |
$h = string.hashMD5( $o_key_pad . string.hashMD5( $i_key_pad . $data )); | |
return $h; | |
} | |
sub SHA1( $key, $data ) { | |
$blocksize = 64; # SHA1 blocksize | |
$s00_64 = | |
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" . | |
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" . | |
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" . | |
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; | |
$s5c_64 = | |
"\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c" . | |
"\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c" . | |
"\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c" . | |
"\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c"; | |
$s36_64 = | |
"\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36" . | |
"\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36" . | |
"\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36" . | |
"\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36"; | |
if( string.length( $key ) > $blocksize ) $key = string.hashSHA1( $key ); | |
if( string.length( $key ) < $blocksize ) $key = string.replaceBytes( $s00_64, $key, 0 ); | |
$o_key_pad = string_xor( $s5c_64, $key ); | |
$i_key_pad = string_xor( $s36_64, $key ); | |
$h = string.hashSHA1( $o_key_pad . string.hashSHA1( $i_key_pad . $data )); | |
return $h; | |
} | |
sub string_xor( $a, $b ) { | |
$r = ""; | |
while( string.length( $a ) ) { | |
$a1 = string.left( $a, 1 ); $a = string.skip( $a, 1 ); | |
$b1 = string.left( $b, 1 ); $b = string.skip( $b, 1 ); | |
$r = $r . chr( ord( $a1 ) ^ ord ( $b1 ) ); | |
} | |
return $r; | |
} |
# Performance and correctness tests for libHMAC.rts | |
# | |
# Apply this rule to an HTTP virtual server and submit a request to run these tests | |
import libHMAC.rts as hmac; | |
# Correctness tests | |
$r = "Test cases from http://tools.ietf.org/html/draft-cheng-hmac-test-cases-00:\n\n"; | |
$r .= testcorrectness( 1, "MD5", | |
"0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", | |
"Hi There", | |
"0x9294727a3638bb1c13f48ef8158bfc9d" ); | |
$r .= testcorrectness( 2, "MD5", | |
"Jefe", | |
"what do ya want for nothing?", | |
"0x750c783e6ab0b503eaa86e310a5db738" ); | |
$a = ""; for( $i = 0; $i < 50; $i++ ) $a .= "\xdd"; | |
$r .= testcorrectness( 3, "MD5", | |
"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", | |
$a, | |
"0x56be34521d144c88dbb8c733f0e8b3f6" ); | |
$a = ""; for( $i = 0; $i < 50; $i++ ) $a .= "\xcd"; | |
$r .= testcorrectness( 4, "MD5", | |
"0x0102030405060708090a0b0c0d0e0f10111213141516171819", | |
$a, | |
"0x697eaf0aca3a3aea3a75164746ffaa79" ); | |
$r .= testcorrectness( 5, "MD5", | |
"0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", | |
"Test With Truncation", | |
"0x56461ef2342edc00f9bab995690efd4c" ); | |
$a = ""; for( $i = 0; $i < 80; $i++ ) $a .= "\xaa"; | |
$r .= testcorrectness( 6, "MD5", | |
$a, | |
"Test Using Larger Than Block-Size Key - Hash Key First", | |
"0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd" ); | |
$r .= testcorrectness( 7, "MD5", | |
$a, | |
"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", | |
"0x6f630fad67cda0ee1fb1f562db3aa53e" ); | |
$r .= testcorrectness( 1, "SHA1", | |
"0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", | |
"Hi There", | |
"0xb617318655057264e28bc0b6fb378c8ef146be00" ); | |
$r .= testcorrectness( 2, "SHA1", | |
"Jefe", | |
"what do ya want for nothing?", | |
"0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79" ); | |
$a = ""; for( $i = 0; $i < 50; $i++ ) $a .= "\xdd"; | |
$r .= testcorrectness( 3, "SHA1", | |
"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", | |
$a, | |
"0x125d7342b9ac11cd91a39af48aa17b4f63f175d3" ); | |
$a = ""; for( $i = 0; $i < 50; $i++ ) $a .= "\xcd"; | |
$r .= testcorrectness( 4, "SHA1", | |
"0x0102030405060708090a0b0c0d0e0f10111213141516171819", | |
$a, | |
"0x4c9007f4026250c6bc8414f9bf50c86c2d7235da" ); | |
$r .= testcorrectness( 5, "SHA1", | |
"0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", | |
"Test With Truncation", | |
"0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04" ); | |
$a = ""; for( $i = 0; $i < 80; $i++ ) $a .= "\xaa"; | |
$r .= testcorrectness( 6, "SHA1", | |
$a, | |
"Test Using Larger Than Block-Size Key - Hash Key First", | |
"0xaa4ae5e15272d00e95705637ce8a3b55ed402112" ); | |
$r .= testcorrectness( 7, "SHA1", | |
$a, | |
"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", | |
"0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91" ); | |
$r .= "\nPerformance tests (running on single core):\n\n"; | |
$r .= testperformance( "MD5" ); | |
$r .= testperformance( "SHA1" ); | |
http.sendResponse( 200, "text/plain", $r, "" ); | |
#--------------------------------- | |
sub testcorrectness( $num, $method, $k, $d, $h ) { | |
if( string.startsWith( $k, "0x" )) $k = string.hexdecode( string.skip( $k, 2 )); | |
if( string.startsWith( $d, "0x" )) $d = string.hexdecode( string.skip( $d, 2 )); | |
if( string.startsWith( $h, "0x" )) $h = string.hexdecode( string.skip( $h, 2 )); | |
$r = "Test case #".$num.":"; | |
if( $method == "MD5" ) { | |
$r .= " Testing HMAC-MD5... "; | |
if( hmac.MD5( $k, $d ) == $h ) { | |
$r .= "passed\n"; | |
} else { | |
$r .= "failed\n"; | |
} | |
} | |
if( $method == "SHA1" ) { | |
$r .= " Testing HMAC-SHA1... "; | |
if( hmac.SHA1( $k, $d ) == $h ) { | |
$r .= "passed\n"; | |
} else { | |
$r .= "failed\n"; | |
} | |
} | |
return $r; | |
} | |
sub testperformance( $method ) { | |
$k = "This is my key"; | |
$d = "This is the data"; | |
$r = ""; | |
$r .= "Testing performance for HMAC-".$method."\n"; | |
# How long do 1000 hash operations take? | |
$start = sys.time.highres(); | |
if( $method == "MD5" ) { | |
for( $i = 0; $i < 1000; $i++ ) hmac.MD5( $k, $d ); | |
} else if( $method == "SHA1" ) { | |
for( $i = 0; $i < 1000; $i++ ) hmac.SHA1( $k, $d ); | |
} | |
$elapsed = sys.time.highres() - $start; | |
$r .= " 1000 operations took ".$elapsed."s\n"; | |
# Estimate how many operations we can perform in 5 seconds | |
$count = math.rint( 5*1000/$elapsed ); | |
$start = sys.time.highres(); | |
if( $method == "MD5" ) { | |
for( $i = 0; $i < $count; $i++ ) hmac.MD5( $k, $d ); | |
} else if( $method == "SHA1" ) { | |
for( $i = 0; $i < $count; $i++ ) hmac.SHA1( $k, $d ); | |
} | |
$elapsed = sys.time.highres() - $start; | |
$r .= " ".$count." operations took ".$elapsed." s\n"; | |
$r .= " Estimated rate: " . ( $count / $elapsed ) . " HMAC-".$method."/s per core\n\n"; | |
return $r; | |
} |