The Trunk: System-ul.773.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

The Trunk: System-ul.773.mcz

commits-2
Levente Uzonyi uploaded a new version of System to project The Trunk:
http://source.squeak.org/trunk/System-ul.773.mcz

==================== Summary ====================

Name: System-ul.773
Author: ul
Time: 26 October 2015, 3:58:12.896 am
UUID: 6bc40bec-54a9-43e1-ae6d-f4fc730cdc16
Ancestors: System-mt.772

SecureHashAlgorithm speedups:
- avoid allocations
- simplified hash function

=============== Diff against System-mt.772 ===============

Item was changed:
  Object subclass: #SecureHashAlgorithm
+ instanceVariableNames: 'totalA totalB totalC totalD totalE totals expandBuffer t1 t2 a b c d e t'
+ classVariableNames: 'K1 K2 K3 K4 TA TB TC TD TE TI'
- instanceVariableNames: 'totalA totalB totalC totalD totalE totals'
- classVariableNames: 'K1 K2 K3 K4'
  poolDictionaries: ''
  category: 'System-Digital Signatures'!
 
  !SecureHashAlgorithm commentStamp: '<historical>' prior: 0!
  This class implements the Secure Hash Algorithm (SHA) described in the U.S. government's Secure Hash Standard (SHS). This standard is described in FIPS PUB 180-1, "SECURE HASH STANDARD", April 17, 1995.
 
  The Secure Hash Algorithm is also described on p. 442 of 'Applied Cryptography: Protocols, Algorithms, and Source Code in C' by Bruce Scheier, Wiley, 1996.
 
  See the comment in class DigitalSignatureAlgorithm for details on its use.
 
  Implementation notes:
  The secure hash standard was created with 32-bit hardware in mind. All arithmetic in the hash computation must be done modulo 2^32. This implementation uses ThirtyTwoBitRegister objects to simulate hardware registers; this implementation is about six times faster than using LargePositiveIntegers (measured on a Macintosh G3 Powerbook). Implementing a primitive to process each 64-byte buffer would probably speed up the computation by a factor of 20 or more.
  !

Item was changed:
  ----- Method: SecureHashAlgorithm class>>initialize (in category 'class initialization') -----
  initialize
  "SecureHashAlgorithm initialize"
  "For the curious, here's where these constants come from:
   #(2 3 5 10) collect: [:x | ((x sqrt / 4.0) * (2.0 raisedTo: 32)) truncated hex]"
 
  K1 := ThirtyTwoBitRegister fromInteger: 16r5A827999.
  K2 := ThirtyTwoBitRegister fromInteger: 16r6ED9EBA1.
  K3 := ThirtyTwoBitRegister fromInteger: 16r8F1BBCDC.
  K4 := ThirtyTwoBitRegister fromInteger: 16rCA62C1D6.
+
+ TA := ThirtyTwoBitRegister fromInteger: 16r67452301.
+ TB := ThirtyTwoBitRegister fromInteger: 16rEFCDAB89.
+ TC := ThirtyTwoBitRegister fromInteger: 16r98BADCFE.
+ TD := ThirtyTwoBitRegister fromInteger: 16r10325476.
+ TE := ThirtyTwoBitRegister fromInteger: 16rC3D2E1F0.
+ (TI := Bitmap new: 5)
+ at: 1 put: 16r67452301;
+ at: 2 put: 16rEFCDAB89;
+ at: 3 put: 16r98BADCFE;
+ at: 4 put: 16r10325476;
+ at: 5 put: 16rC3D2E1F0!
- !

Item was changed:
  ----- Method: SecureHashAlgorithm>>expandedBlock: (in category 'private') -----
  expandedBlock: aByteArray
  "Convert the given 64 byte buffer into 80 32-bit registers and answer the result."
+
+ | src |
- | out src v |
- out := Array new: 80.
  src := 1.
  1 to: 16 do: [:i |
+ (expandBuffer at: i) loadFrom: aByteArray at: src.
- out at: i put: (ThirtyTwoBitRegister fromByteArray: aByteArray at: src).
  src := src + 4].
 
  17 to: 80 do: [:i |
+ t1
+ loadFrom: (expandBuffer at: i - 3);
+ bitXor: (expandBuffer at: i - 8);
+ bitXor: (expandBuffer at: i - 14);
+ bitXor: (expandBuffer at: i - 16);
- v := (out at: i - 3) copy.
- v bitXor: (out at: i - 8);
- bitXor: (out at: i - 14);
- bitXor: (out at: i - 16);
  leftRotateBy: 1.
+ (expandBuffer at: i) loadFrom: t1 ]
- out at: i put: v].
- ^ out
  !

Item was changed:
  ----- Method: SecureHashAlgorithm>>finalHash (in category 'private') -----
  finalHash
  "Concatenate the final totals to build the 160-bit integer result."
  "Details: If the primitives are supported, the results are in the totals array. Otherwise, they are in the instance variables totalA through totalE."
 
+ | result |
+ result := ByteArray new: 20.
+ totals
+ ifNil: [ "compute final hash when not using primitives"
+ result
+ unsignedShortAt: 1 put: totalE low bigEndian: false;
+ unsignedShortAt: 3 put: totalE hi bigEndian: false;
+ unsignedShortAt: 5 put: totalD low bigEndian: false;
+ unsignedShortAt: 7 put: totalD hi bigEndian: false;
+ unsignedShortAt: 9 put: totalC low bigEndian: false;
+ unsignedShortAt: 11 put: totalC hi bigEndian: false;
+ unsignedShortAt: 13 put: totalB low bigEndian: false;
+ unsignedShortAt: 15 put: totalB hi bigEndian: false;
+ unsignedShortAt: 17 put: totalA low bigEndian: false;
+ unsignedShortAt: 19 put: totalA hi bigEndian: false ]
+ ifNotNil: [ "compute final hash when using primitives"
+ result
+ unsignedLongAt: 1 put: (totals at: 5) bigEndian: false;
+ unsignedLongAt: 5 put: (totals at: 4) bigEndian: false;
+ unsignedLongAt: 9 put: (totals at: 3) bigEndian: false;
+ unsignedLongAt: 13 put: (totals at: 2) bigEndian: false;
+ unsignedLongAt: 17 put: (totals at: 1) bigEndian: false ].
+ ^(LargePositiveInteger new: result size)
+ replaceFrom: 1
+ to: result size
+ with: result
+ startingAt: 1;
+ normalize!
- | r |
- totals ifNil: [  "compute final hash when not using primitives"
- ^ (totalA asInteger bitShift: 128) +
-  (totalB asInteger bitShift:  96) +
-  (totalC asInteger bitShift:  64) +
-  (totalD asInteger bitShift:  32) +
-  (totalE asInteger)].
-
- "compute final hash when using primitives"
- r := 0.
- 1 to: 5 do: [:i |
- r := r bitOr: ((totals at: i) bitShift: (32 * (5 - i)))].
- ^ r
- !

Item was added:
+ ----- Method: SecureHashAlgorithm>>hashFunction: (in category 'private') -----
+ hashFunction: i
+ "Compute the hash function for the i-th step of the block hash loop. We number our steps 1-80, versus the 0-79 of the standard."
+ "Details: There are four functions, one for each 20 iterations. The second and fourth are the same."
+
+ t1 loadFrom: b.
+ i <= 20 ifTrue: [
+ t2
+ loadFrom: b;
+ bitInvert;
+ bitAnd: d.
+ ^t1
+ bitAnd: c;
+ bitOr: t2 ].
+ i <= 40 ifTrue: [
+ ^t1
+ bitXor: c;
+ bitXor: d ].
+ i <= 60 ifTrue: [
+ t2
+ loadFrom: b;
+ bitOr: c;
+ bitAnd: d.
+ ^t1
+ bitAnd: c;
+ bitOr: t2 ].
+ ^t1
+ bitXor: c;
+ bitXor: d
+ !

Item was removed:
- ----- Method: SecureHashAlgorithm>>hashFunction:of:with:with: (in category 'private') -----
- hashFunction: i of: x with: y with: z
- "Compute the hash function for the i-th step of the block hash loop. We number our steps 1-80, versus the 0-79 of the standard."
- "Details: There are four functions, one for each 20 iterations. The second and fourth are the same."
-
- i <= 20 ifTrue: [^ x copy bitAnd: y; bitOr: (x copy bitInvert; bitAnd: z)].
- i <= 40 ifTrue: [^ x copy bitXor: y; bitXor: z].
- i <= 60 ifTrue: [^ x copy bitAnd: y; bitOr: (x copy bitAnd: z); bitOr: (y copy bitAnd: z)].
- ^ x copy bitXor: y; bitXor: z
- !

Item was changed:
  ----- Method: SecureHashAlgorithm>>hashInteger:seed: (in category 'public') -----
  hashInteger: aPositiveInteger seed: seedInteger
  "Hash the given positive integer. The integer to be hashed should have 512 or fewer bits. This entry point is used in the production of random numbers"
 
  | buffer dstIndex |
  "Initialize totalA through totalE to their seed values."
+ totals
+ ifNil: [
+ totalA := ThirtyTwoBitRegister
+ fromInteger: ((seedInteger bitShift: -128) bitAnd: 16rFFFFFFFF).
+ totalB := ThirtyTwoBitRegister
+ fromInteger: ((seedInteger bitShift: -96) bitAnd: 16rFFFFFFFF).
+ totalC := ThirtyTwoBitRegister
+ fromInteger: ((seedInteger bitShift: -64) bitAnd: 16rFFFFFFFF).
+ totalD := ThirtyTwoBitRegister
+ fromInteger: ((seedInteger bitShift: -32) bitAnd: 16rFFFFFFFF).
+ totalE := ThirtyTwoBitRegister
+ fromInteger: (seedInteger bitAnd: 16rFFFFFFFF) ]
+ ifNotNil: [
+ totals
+ at: 1 put: ((seedInteger bitShift: -128) bitAnd: 16rFFFFFFFF);
+ at: 2 put: ((seedInteger bitShift: -96) bitAnd: 16rFFFFFFFF);
+ at: 3 put: ((seedInteger bitShift: -64) bitAnd: 16rFFFFFFFF);
+ at: 4 put: ((seedInteger bitShift: -32) bitAnd: 16rFFFFFFFF);
+ at: 5 put: (seedInteger bitAnd: 16rFFFFFFFF) ].
- totalA := ThirtyTwoBitRegister
- fromInteger: ((seedInteger bitShift: -128) bitAnd: 16rFFFFFFFF).
- totalB := ThirtyTwoBitRegister
- fromInteger: ((seedInteger bitShift: -96) bitAnd: 16rFFFFFFFF).
- totalC := ThirtyTwoBitRegister
- fromInteger: ((seedInteger bitShift: -64) bitAnd: 16rFFFFFFFF).
- totalD := ThirtyTwoBitRegister
- fromInteger: ((seedInteger bitShift: -32) bitAnd: 16rFFFFFFFF).
- totalE := ThirtyTwoBitRegister
- fromInteger: (seedInteger bitAnd: 16rFFFFFFFF).
- self initializeTotalsArray.
-
  "pad integer with zeros"
  buffer := ByteArray new: 64.
  dstIndex := 0.
  aPositiveInteger digitLength to: 1 by: -1 do: [:i |
  buffer at: (dstIndex := dstIndex + 1) put: (aPositiveInteger digitAt: i)].
 
  "process that one block"
  self processBuffer: buffer.
 
  ^ self finalHash
  !

Item was changed:
  ----- Method: SecureHashAlgorithm>>hashStream: (in category 'public') -----
  hashStream: aPositionableStream
  "Hash the contents of the given stream from the current position to the end using the Secure Hash Algorithm. The SHA algorithm is defined in FIPS PUB 180-1. It is also described on p. 442 of 'Applied Cryptography: Protocols, Algorithms, and Source Code in C' by Bruce Scheier, Wiley, 1996."
  "SecureHashAlgorithm new hashStream: (ReadStream on: 'foo')"
 
  | startPosition buf bitLength |
  self initializeTotals.
 
  "(SecureHashAlgorithm new hashMessage: '') radix: 16
  => 'DA39A3EE5E6B4B0D3255BFEF95601890AFD80709'"
+ aPositionableStream atEnd ifTrue: [self processFinalBuffer: #[] bitLength: 0].
- aPositionableStream atEnd ifTrue: [self processFinalBuffer: #() bitLength: 0].
 
  startPosition := aPositionableStream position.
+ buf := ByteArray new: 64.
  [aPositionableStream atEnd] whileFalse: [
+ buf := aPositionableStream next: 64 into: buf startingAt: 1.
- buf := aPositionableStream next: 64.
  (aPositionableStream atEnd not and: [buf size = 64])
  ifTrue: [self processBuffer: buf]
  ifFalse: [
  bitLength := (aPositionableStream position - startPosition) * 8.
  self processFinalBuffer: buf bitLength: bitLength]].
 
  ^ self finalHash
  !

Item was added:
+ ----- Method: SecureHashAlgorithm>>initialize (in category 'initialize-release') -----
+ initialize
+
+ self primHasSecureHashPrimitive
+ ifTrue: [
+ totals := Bitmap new: 5.
+ expandBuffer := Bitmap new: 80 ]
+ ifFalse: [
+ totalA := ThirtyTwoBitRegister new.
+ totalB := ThirtyTwoBitRegister new.
+ totalC := ThirtyTwoBitRegister new.
+ totalD := ThirtyTwoBitRegister new.
+ totalE := ThirtyTwoBitRegister new.
+ expandBuffer := Array new: 80.
+ 1 to: 80 do: [ :index |
+ expandBuffer at: index put: ThirtyTwoBitRegister new ].
+ t1 := ThirtyTwoBitRegister new.
+ t2 := ThirtyTwoBitRegister new.
+ t := ThirtyTwoBitRegister new.
+ a := ThirtyTwoBitRegister new.
+ b := ThirtyTwoBitRegister new.
+ c := ThirtyTwoBitRegister new.
+ d := ThirtyTwoBitRegister new.
+ e := ThirtyTwoBitRegister new ]!

Item was changed:
  ----- Method: SecureHashAlgorithm>>initializeTotals (in category 'private') -----
  initializeTotals
  "Initialize totalA through totalE to their seed values."
 
+ totals
+ ifNil: [
+ "total registers for use when primitives are absent"
+ totalA loadFrom: TA.
+ totalB loadFrom: TB.
+ totalC loadFrom: TC.
+ totalD loadFrom: TD.
+ totalE loadFrom: TE ]
+ ifNotNil: [
+ totals
+ replaceFrom: 1
+ to: totals size
+ with: TI
+ startingAt: 1 ]!
- "total registers for use when primitives are absent"
- totalA := ThirtyTwoBitRegister fromInteger: 16r67452301.
- totalB := ThirtyTwoBitRegister fromInteger: 16rEFCDAB89.
- totalC := ThirtyTwoBitRegister fromInteger: 16r98BADCFE.
- totalD := ThirtyTwoBitRegister fromInteger: 16r10325476.
- totalE := ThirtyTwoBitRegister fromInteger: 16rC3D2E1F0.
- self initializeTotalsArray.
- !

Item was removed:
- ----- Method: SecureHashAlgorithm>>initializeTotalsArray (in category 'private') -----
- initializeTotalsArray
- "Initialize the totals array from the registers for use with the primitives."
-
- totals := Bitmap new: 5.
- totals at: 1 put: totalA asInteger.
- totals at: 2 put: totalB asInteger.
- totals at: 3 put: totalC asInteger.
- totals at: 4 put: totalD asInteger.
- totals at: 5 put: totalE asInteger.
- !

Item was changed:
  ----- Method: SecureHashAlgorithm>>processBuffer: (in category 'private') -----
  processBuffer: aByteArray
  "Process given 64-byte buffer, accumulating the results in totalA through totalE."
 
+ | tmp |
+ totals ifNotNil: [ ^self processBufferUsingPrimitives: aByteArray ].
- | a b c d e w tmp |
- self primHasSecureHashPrimitive
- ifTrue: [^ self processBufferUsingPrimitives: aByteArray]
- ifFalse: [totals := nil].
 
- "initialize registers a through e from the current totals"
- a := totalA copy.
- b := totalB copy.
- c := totalC copy.
- d := totalD copy.
- e := totalE copy.
-
  "expand and process the buffer"
+ self expandedBlock: aByteArray.
+
+ "initialize registers a through e from the current totals"
+ a loadFrom: totalA.
+ b loadFrom: totalB.
+ c loadFrom: totalC.
+ d loadFrom: totalD.
+ e loadFrom: totalE.
- w := self expandedBlock: aByteArray.
  1 to: 80 do: [:i |
+ t
+ loadFrom: a;
+ leftRotateBy: 5;
+ += (self hashFunction: i);
- tmp := (a copy leftRotateBy: 5)
- += (self hashFunction: i of: b with: c with: d);
  += e;
+ += (expandBuffer at: i);
- += (w at: i);
  += (self constantForStep: i).
+ tmp := e.
  e := d.
  d := c.
  c := b leftRotateBy: 30.
  b := a.
+ a := t.
+ t := tmp ].
- a := tmp].
 
  "add a through e into total accumulators"
  totalA += a.
  totalB += b.
  totalC += c.
  totalD += d.
  totalE += e.
  !

Item was changed:
  ----- Method: SecureHashAlgorithm>>processBufferUsingPrimitives: (in category 'private') -----
  processBufferUsingPrimitives: aByteArray
  "Process given 64-byte buffer using the primitives, accumulating the results in totals."
 
- | w |
  "expand and process the buffer"
+ self
+ primExpandBlock: aByteArray into: expandBuffer;
+ primHashBlock: expandBuffer using: totals.
- w := Bitmap new: 80.
- self primExpandBlock: aByteArray into: w.
- self primHashBlock: w using: totals.
  !