'From Squeak 2.2 of Sept 23, 1998 on 7 November 2005 at 5:42:15 pm'! ReadWriteStream subclass: #EncryptedStream instanceVariableNames: 'ncryptor stream ' classVariableNames: '' poolDictionaries: '' category: 'Spoon-Security'! Object subclass: #MessageDigest instanceVariableNames: '' classVariableNames: 'Padding ' poolDictionaries: '' category: 'Spoon-Crypto'! MessageDigest subclass: #MD2 instanceVariableNames: 'checksum count state ' classVariableNames: 'MD2Padding Sbox ' poolDictionaries: '' category: 'Spoon-Crypto'! MessageDigest subclass: #MD4 instanceVariableNames: 'bitCount byteBuffer byteCount state savedState wordBuffer ' classVariableNames: '' poolDictionaries: '' category: 'Spoon-Crypto'! MessageDigest subclass: #MD5 instanceVariableNames: 'bitCount byteBuffer byteCount state savedState wordBuffer ' classVariableNames: 'T ' poolDictionaries: '' category: 'Spoon-Crypto'! Object subclass: #NameOfClass instanceVariableNames: 'instVarName1 instVarName2 ' classVariableNames: 'ClassVarName1 ClassVarName2 ' poolDictionaries: '' category: 'Spoon-Crypto'! Object subclass: #Password instanceVariableNames: '' classVariableNames: 'MasterKey Passwords ' poolDictionaries: '' category: 'Spoon-Security'! Object subclass: #PasswordBasedEncryptor instanceVariableNames: 'salt iteration password ' classVariableNames: '' poolDictionaries: '' category: 'Spoon-Crypto'! Object subclass: #Preferences instanceVariableNames: '' classVariableNames: 'DesktopColor FlagDictionary SecretVaultFileName SecretVaultPassword ' poolDictionaries: '' category: 'System-Support'! MessageDigest subclass: #SHA1 instanceVariableNames: 'bitCount byteBuffer byteCount state savedState wordBuffer workBuffer ' classVariableNames: 'K ' poolDictionaries: '' category: 'Spoon-Crypto'! MessageDigest subclass: #SHA256 instanceVariableNames: 'bitCount byteBuffer byteCount state savedState wordBuffer workBuffer ' classVariableNames: 'K ' poolDictionaries: '' category: 'Spoon-Crypto'! Object subclass: #SymmetricStreamCipher instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Spoon-Crypto'! SymmetricStreamCipher subclass: #ARC4 instanceVariableNames: 'i j sbox ' classVariableNames: '' poolDictionaries: '' category: 'Spoon-Crypto'! !Author commentStamp: 'crl 2/12/2004 22:05' prior: 0! ' Each of my instances describes an author of behavior in a system somewhere in the universe. Author: Craig Latta ! !Authority commentStamp: 'crl 2/13/2004 14:13' prior: 0! ' I am an abstract class. Instances of my concrete subclasses identify the naming authority of a URI. Author: asparagi! !BehaviorialLiteralMarker commentStamp: 'crl 2/12/2004 22:21' prior: 0! ' Each of my instances indicates, to a remote system reading a serialized CompiledMethod, a method literal which refers some aspect of an installed behavior (the behavior itself, one of its class pool elements, or the method-class for a metaclass super-send method). Author: Craig Latta ! !ClassLiteralMarker commentStamp: 'crl 2/12/2004 22:19' prior: 0! ' Each of my instances indicates, to a remote system reading a serialized CompiledMethod, a method literal which refers to an installed class (a system dictionary element). Author: Craig Latta ! !ClassPoolLiteralMarker commentStamp: 'crl 2/12/2004 22:21' prior: 0! ' Each of my instances indicates, to a remote system reading a serialized CompiledMethod, a method literal which refers to class pool element. Author: Craig Latta ! !EncryptedStream methodsFor: 'streaming'! atEnd ^ stream atEnd .! ! !EncryptedStream methodsFor: 'streaming'! close stream close.! ! !EncryptedStream methodsFor: 'streaming'! flush stream flush.! ! !EncryptedStream methodsFor: 'streaming' stamp: 'il prior: 34077985!! '! next "This only works for stream ciphers at the moment." | inBuffer outBuffer nextC | "wow. this is patently laughable. Creating a new ByteArray each time you want to decrypt" "a single character in an encrypted stream. Oh well... gives me an opportunity to" "dramatically increase performance later." inBuffer _ ByteArray new: 1. outBuffer _ ByteArray new: 1. inBuffer at: 1 put: ( ( stream next ) asInteger ). ncryptor decrypt: inBuffer into: outBuffer. nextC _ outBuffer at: 1. outBuffer at: 1 put: 0. inBuffer at: 1 put: 0. ^ nextC . ! ! !EncryptedStream methodsFor: 'streaming' stamp: 'msh 11/7/2005 12:56'! nextPut: aChar "This only works for stream ciphers at the moment." | inBuffer outBuffer | "wow. this is patently laughable. Creating a new ByteArray each time you want to decrypt" "a single character in an encrypted stream. Oh well... gives me an opportunity to" "dramatically increase performance later." inBuffer _ ByteArray new: 1. outBuffer _ ByteArray new: 1. inBuffer at: 1 put: ( aChar asInteger ). ncryptor encrypt: inBuffer into: outBuffer. stream nextPut: ( ( outBuffer at: 1 ) asCharacter ). inBuffer at: 1 put: 0. outBuffer at: 1 put: 0. ! ! !EncryptedStream methodsFor: 'private'! ncryptor: anEncryptor ncryptor _ anEncryptor.! ! !EncryptedStream methodsFor: 'private'! stream: aStream stream _ aStream.! ! !EncryptedStream class methodsFor: 'initialization' stamp: 'msh 11/7/2005 12:53'! on: aStream with: anEncryptor ^ (self basicNew) ncryptor: anEncryptor; stream: aStream.! ! !Evaluation commentStamp: 'crl 2/12/2004 22:33' prior: 0! ' Each of my instances evaluates a string provided by a remote system when read from a remote system. Author: Craig Latta ! !EvaluationRequest commentStamp: 'crl 2/12/2004 22:34' prior: 0! ' Each of my instances represents a request to a remote system for a source string which, when evaluated, yields an object equivalent to an exposed object exposed by that remote system. Author: Craig Latta ! !ExternalResource commentStamp: 'crl 2/13/2004 12:21' prior: 0! ' I am an abstract Class. Instances of my concrete subclasses represent resources used by the system but maintained outside of it. Examples include external storage and network resources. instance variable: handle an opaque SmallInteger, the meaning of which is defined externally, used in external operations involving an instance Author: Craig Latta ! !ExternalStream commentStamp: 'crl 2/13/2004 14:03' prior: 0! ' I am an abstract Class. Instances of my concrete subclasses provide access to external stream resources. Author: Craig Latta ! !FillInTheBlank class methodsFor: 'as yet unclassified' stamp: 'il prior: 34094800!! '! request: queryString ^ self request: queryString initialAnswer: '' centerAt: Sensor cursorPoint! ! !GlobalLiteralMarker commentStamp: 'crl 2/12/2004 22:21' prior: 0! ' Each of my instances indicates, to a remote system reading a serialized CompiledMethod, a method literal which refers to non-behavior global object. Author: Craig Latta ! !HostAuthority commentStamp: 'crl 2/13/2004 14:13' prior: 0! ' Each of my instances identifies a host, port, and user information for accessing the indicated service; together these constitute the authority of a URI. instance variables: - userinfo a String representing user information for accessing an authority - host a HostIdentifier - port an Integer indicating the port on which to contact host Author: asparagi! !HostIdentifier commentStamp: 'crl 2/13/2004 14:13' prior: 0! ' I am an abstract class. Instances of my concrete subclasses identify a host machine, presumably one which can be contacted via a network. Author: asparagi! !DomainName commentStamp: 'crl 2/13/2004 14:13' prior: 0! ' My instances store domain names, someday as specified in RFCs 1034 and 1035; currently as specified in RFC 2396. instance variables: - nameSegments a collection of Strings representing this domain name Author: asparagi! !IPv4Address commentStamp: 'crl 2/13/2004 14:14' prior: 0! ' My instances represent IPv4 network addresses, used to represent a host in a URI. RFC 2396 allows 1 or more digits in each octet of the IP address, which would allow octets such as 256 or 1004, but clearly each octet of an IPv4 address must fit in 1 byte, i.e. be between 0 and 255. instance variables: - address 4 bytes representing an IPv4 network address Author: asparagi! !Manifest commentStamp: 'crl 2/12/2004 22:24' prior: 0! ' I am an abstract Class. Each instance of my concrete subclasses compactly describes the existence or absence of elements in a collection. These instances are used in Module synchronization, in order for a remote system to describe which elements of a set fulfill some criterion with a minimum of network traffic. Author: Craig Latta ! !MessageDigest commentStamp: '' prior: 0! MessageDigest is the abstract superclass for the concrete message digest implementations. Message Digest Codes (aka Cryptographic Hash Functions) compute a seemingly unpredictable, fixed length "hash" from arbitrary input. They're used as building blocks for other algorithms including digital signature, message authentication code (MAC), Pseudo Random Number Generators (PRNG) and password based encryption algorithms. Message Digest Codes are also used to "hash passwords" and as part of the ubiquitous SSL/TLS protocol suite. They're sort of like the "sonic screwdriver" of the crypto world. Note that this class simply computes hashes based on strings of input bytes. That is, we take a fixed array of values that we assume are bytes (i.e. - integral values between 0 and 255 inclusive) and operate directly on them. Keep this in mind as you start playing with Unicode and any other representation that can use more than one byte for a single character. The tests in the Crypto-Test SUnit test suite are useful in understanding how these classes work. But since I tend to cringe anytime anyone else says their code is "self documenting," I should probably put my money where my mouth is and say a few things about using these classes. Message Digest Functions Cryptographic Hash Functions are implemented as subclasses of the MessageDigest class. This class encapsulates some common behavior inherited by all it's subclasses. There are four protocols used by the MessageDigest subclasses: digesting, output size, private, and sensitive data. (Actually, the sensitive data protocol is implemented by the MessageDigest class, but as it's an abstract super class, it depends on subclasses to actually express the protocol's behavior.) instance creation If you want to produce a cryptographic hash, then the first step is to create an instance of a message digest object. For example, let's see how we would create an instance of a SHA1 message digest object. | a | a _ SHA1 new. digesting protocol Now that we have a SHA1 instance, let's start digesting something. We do this with the update: message. We can call the update: function as many times as needed. Note that the MessageDigest subclasses are designed to take ByteArray's. a update: ('this is a test' asByteArray). a update: ('here is some more text to be hashed' asByteArray). To produce a message digest, use the digest message. The digest message returns a ByteArray containing the message digest. | b | b _ a digest. If you have an existing array, you can tell a MessageDigest object to put a digest into it with the digest: at: message. The first parameter to this message is an existing array, while the second parameter is an index into the array where you want the digest to go. The following example puts a message digest in elements 12 through 32 in the byte array b. | b | b _ ByteArray new: 50. a digest: b at: 12. After creating a message digest, you may want to create another digest for another data stream. You can do this using the same MessageDigest object, but you must call the reinitialize message first. a reinitialize. output size protocol Not all hash functions produce the same sized output. If you want to know how large the output a particular function will produce, you can use the outputSize message. It responds with an integer that is the size a buffer would have to be to hold it's output. The digest message uses this function to create a byte array to hold the digest it returns: |rv| rv _ ByteArray new: (a outputSize). Code archeologists will note that there is an outputSize message that takes an integer as a parameter. This is designed mostly for encipherment algorithms where the output size is not fixed. For consistency, the message is replicated in the MessageDigest classes and does pretty much the same thing as the plain ol' outputSize message. sensitive data protocol One way that attackers can recover sensitive information is by looking at swap files, or live memory heaps. In an ideal world they wouldn't be able to get any information from looking at these sorts of things, but in the real world we have to worry about these corner cases. The clearSensitiveData protocol zeroizes any sensitive information stored in the class' instance variables. You should do this after using a message digest object and before the object falls out of scope. a clearSensitiveData private protocol The private protocol is.. uh... private. You are, of course, allowed and encouraged to examine how we actually produce our message digests, but we should warn you that there's still some refactoring left to be done on the MessageDigest subclasses, so don't say we didn't warn you!!! !MessageDigest methodsFor: 'output size' stamp: 'msh 6/16/2003 23:16'! outputSize: anInteger "Given in input block of size anInteger, return the size of the output (in bytes)." ^ self outputSize .! ! !MessageDigest methodsFor: 'sensitive data' stamp: 'msh 6/16/2003 23:18'! clearSensitiveData self reinitialize.! ! !MessageDigest methodsFor: 'digesting' stamp: 'msh 6/16/2003 23:20'! digest "return a digest, based on the content of the digesting context." | rv | rv _ ByteArray new: ( self outputSize ). self digest: rv at: 1. ^ rv .! ! !MessageDigest methodsFor: 'digesting' stamp: 'msh 6/16/2003 23:24'! update: aByteArray self update: aByteArray at: 1 count: (aByteArray size).! ! !MessageDigest methodsFor: 'private' stamp: 'msh 6/16/2003 23:22'! leftRotate: anInteger by: bits ^ (anInteger << bits) bitOr: (anInteger >> (32 - bits)) .! ! !MessageDigest methodsFor: 'private' stamp: 'msh 6/17/2003 02:11'! rightRotate: anInteger by: bits ^ (anInteger >> bits) bitOr: (anInteger << (32 - bits)) .! ! !MD2 commentStamp: '' prior: 0! This class is provided for reverse compatibility. Do not use MD2 in new applications. MD2 is a message digest code invented by Ron Rivest of MIT and RSA Data Security fame. This implementation is taken from the description of the algorithm provided in RFC 1319 (available at the IETF web page at http://www.ietf.org/rfc/rfc1319.txt). MD2 is not recommended for use with new projects. It is included here only to support an old Verisign Certificate that uses MD2 with RSA for digital signature production. New implementations should use SHA1 or SHA256. This class implements three implementation variables and two class variables. * Sbox (class variable) -- This is the substitution table used to create the digest. * MD2Padding (class variable) -- The last 16 byte block of a message is padded to include n bytes of value n. This is an array of arrays that contain those n n bytes. * checksum -- as part of the creation of the message digest, a "checksum" is generated. This variable contains the checksum for all bytes hashed at any given point. * count -- this integer contains the number of bytes input into the hash algorithm modulo 16. * state -- this 48 byte buffer is loaded with 16 bytes at a time, then "transformed" using the algorithm defined in RFC 1319. ! !MD2 methodsFor: 'private' stamp: 'msh 6/13/2003 01:14'! initialize "this method is evoked once by the new method. Do not call this method to initialize" "an instance of this class, call reinitialize instead." checksum _ ByteArray new: 16. count _ 1. state _ ByteArray new: 48.! ! !MD2 methodsFor: 'private' stamp: 'msh 6/13/2003 01:20'! transform "Apply the MD2 transform to the current state" | t | t _ checksum at: 16. 1 to: 16 do: [ :i | t _ (checksum at: i) bitXor: (Sbox at: (((state at: (16 +i)) bitXor: t) + 1) ). checksum at: i put: t. ]. t _ 0. 1 to: 18 do: [ :i | 1 to: 48 do: [ :j | t _ (state at: j) bitXor: (Sbox at: (1 + t) ). state at: j put: t. ]. t _ ( t + i - 1 ) bitAnd: 16rFF. ]. count _ 1.! ! !MD2 methodsFor: 'digesting' stamp: 'msh 6/13/2003 01:10'! digest: aByteArray at: anInteger "return a digest, based on the content of the digesting context." self update: (MD2Padding at: count). self update: checksum. 1 to: 16 do: [ :i | aByteArray at: (anInteger + i - 1) put: (state at: i). ].! ! !MD2 methodsFor: 'digesting' stamp: 'msh 6/13/2003 01:06'! reinitialize "This method reinitializes the state of the current MD2 context." 1 to: (checksum size) do: [ :i | checksum at: i put: 0.]. count _ 1. 1 to: (state size) do: [ :i | state at: i put: 0.].! ! !MD2 methodsFor: 'digesting' stamp: 'msh 6/13/2003 01:10'! update: aByteArray at: anIndex count: aCount "update the digesting context with the contents of aByteArray." anIndex to: (anIndex + aCount - 1) do: [ :i | state at: (16 + count) put: (aByteArray at: i). state at: (32 + count) put: ((state at: count) bitXor: (aByteArray at: i)). count _ count + 1. (count > 16) ifTrue: [ self transform. ]. ].! ! !MD2 methodsFor: 'output size' stamp: 'msh 6/13/2003 01:07'! outputSize ^16.! ! !MD4 commentStamp: '' prior: 0! This class is provided for reverse compatibility reasons only. Do not use MD4 for new applications. MD4 is one of a series of hash functions invented by Ron Rivest of MIT. The algorithm has been published widely; this implementation comes from IETF RFC 1320 ( available at http://www.ietf.org/rfc/rfc1320.txt .) RSA Labs ( the research arm of the commercial venture launched by Dr. Rivest ) has a nice FAQ entry in their RSA Labs FAQ at http://www.rsasecurity.com/rsalabs/node.asp?id=2253 . From this, we learn that attacks on MD4 were developed in the early and mid 90's. The most important line from this page is probably, "Clearly, MD4 should now be considered broken." ! !MD4 methodsFor: 'output size' stamp: 'msh 6/13/2003 01:39'! outputSize ^16.! ! !MD4 methodsFor: 'digesting' stamp: 'msh 6/16/2003 18:20'! digest: aByteArray at: anIndex | currentBitCount mask | currentBitCount _ bitCount. "append padding" ( byteCount < 56 ) ifTrue: [ self update: Padding at: 1 count: ( 56 - byteCount ). ] ifFalse: [ self update: Padding at: 1 count: ( 121 - byteCount ). ]. "add bit count" mask _ 16rFF00000000000000. 1 to: 8 do: [ :i | byteBuffer at: ( 65 - i ) put: ( (currentBitCount bitAnd: mask) >> ( (8 - i) * 8 ) ). mask _ mask >> 8. ]. "transform the final buffer" self transform. "write state to output" aByteArray at: (3 + anIndex) put: ( ( ( state at: 1 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (2 + anIndex) put: ( ( ( state at: 1 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (1 + anIndex) put: ( ( ( state at: 1 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (anIndex) put: ( ( state at: 1 ) bitAnd: 16rFF ). aByteArray at: (7 + anIndex) put: ( ( ( state at: 2 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (6 + anIndex) put: ( ( ( state at: 2 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (5 + anIndex) put: ( ( ( state at: 2 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (4 + anIndex) put: ( ( state at: 2 ) bitAnd: 16rFF ). aByteArray at: (11 + anIndex) put: ( ( ( state at: 3 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (10 + anIndex) put: ( ( ( state at: 3 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (9 + anIndex) put: ( ( ( state at: 3 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (8 + anIndex) put: ( ( state at: 3 ) bitAnd: 16rFF ). aByteArray at: (15 + anIndex) put: ( ( ( state at: 4 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (14 + anIndex) put: ( ( ( state at: 4 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (13 + anIndex) put: ( ( ( state at: 4 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (12 + anIndex) put: ( ( state at: 4 ) bitAnd: 16rFF ).! ! !MD4 methodsFor: 'digesting' stamp: 'msh 6/16/2003 18:02'! reinitialize bitCount _ 0. 1 to: (byteBuffer size) do: [ :i | byteBuffer at: i put: 0 ]. byteCount _ 0. 1 to: (savedState size) do: [ :i | savedState at: i put: 0 ]. state at: 1 put: 16r67452301. state at: 2 put: 16rEFCDAB89. state at: 3 put: 16r98BADCFE. state at: 4 put: 16r10325476. 1 to: (wordBuffer size) do: [ :i | wordBuffer at: i put: 0 ].! ! !MD4 methodsFor: 'digesting' stamp: 'msh 6/16/2003 18:17'! update: aByteArray at: anIndex count: aCount "update the digesting context with the contents of aByteArray." anIndex to: (anIndex + aCount - 1) do: [ :i | byteCount _ byteCount + 1. bitCount _ bitCount + 8. ( byteCount > 64 ) ifTrue: [ byteCount _ 1. self transform. ]. byteBuffer at: byteCount put: (aByteArray at: i). ].! ! !MD4 methodsFor: 'private' stamp: 'msh 6/16/2003 18:10'! bufferConvert "Convert the contents of the byte array byteBuffer into the word array wordBuffer. " | j | 1 to: 16 do: [:i | j _ i - 1 * 4 + 1. wordBuffer at: i put: ((((byteBuffer at: j) bitOr: (byteBuffer at: 1 + j) << 8) bitOr: (byteBuffer at: 2 + j) << 16) bitOr: (byteBuffer at: 3 + j) << 24)]! ! !MD4 methodsFor: 'private' stamp: 'msh 6/16/2003 00:42'! ff: a with: b with: c with: d with: x with: s | t | t _ ( ( wordBuffer at: x ) + ( ( state at: a) + ( ( ( state at: b ) bitAnd: ( state at: c ) ) bitOr: ( ( ( state at: b ) bitInvert ) bitAnd: ( state at: d ) ) ) ) ). state at: a put: ( ( self leftRotate: ( t bitAnd: 16rFFFFFFFF ) by: s ) bitAnd: 16rFFFFFFFF ). t _ 0.! ! !MD4 methodsFor: 'private' stamp: 'msh 6/16/2003 00:42'! gg: a with: b with: c with: d with: x with: s | t | t _ ( 16r5A827999 + ( ( wordBuffer at: x ) + ( ( state at: a ) + ( ( ( state at: b ) bitAnd: ( state at: c ) ) bitOr: ( ( ( state at: b ) bitAnd: ( state at: d ) ) bitOr: ( ( state at: c ) bitAnd: ( state at: d ) ) ) ) ) ) ). state at: a put: ( ( self leftRotate: ( t bitAnd: 16rFFFFFFFF ) by: s ) bitAnd: 16rFFFFFFFF ). t _ 0. ! ! !MD4 methodsFor: 'private' stamp: 'msh 6/16/2003 00:44'! hh: a with: b with: c with: d with: x with: s |t| t _ ( 16r6ED9EBA1 + ( ( wordBuffer at: x ) + ( ( state at: a ) + ( ( state at: b ) bitXor: ( ( state at: c ) bitXor: ( state at: d ) ) ) ) ) ). state at: a put: ( ( self leftRotate: ( t bitAnd: 16rFFFFFFFF ) by: s ) bitAnd: 16rFFFFFFFF ). t _ 0.! ! !MD4 methodsFor: 'private' stamp: 'msh 11/7/2005 01:46'! initialize "this method is evoked once by the new method. Do not call this method to initialize" "an instance of this class, call reinitialize instead." bitCount _ 0. byteBuffer _ ByteArray new: 64. byteCount _ 0. savedState _ Array new: 4. state _ Array new: 4. state at: 1 put: 16r67452301. state at: 2 put: 16rEFCDAB89. state at: 3 put: 16r98BADCFE. state at: 4 put: 16r10325476. wordBuffer _ Array new: 16.! ! !MD4 methodsFor: 'private' stamp: 'msh 6/16/2003 18:20'! transform self bufferConvert. 1 to: 4 do: [ :i | savedState at: i put: (state at: i) ]. self ff: 1 with: 2 with: 3 with: 4 with: 1 with: 3. self ff: 4 with: 1 with: 2 with: 3 with: 2 with: 7. self ff: 3 with: 4 with: 1 with: 2 with: 3 with: 11. self ff: 2 with: 3 with: 4 with: 1 with: 4 with: 19. self ff: 1 with: 2 with: 3 with: 4 with: 5 with: 3. self ff: 4 with: 1 with: 2 with: 3 with: 6 with: 7. self ff: 3 with: 4 with: 1 with: 2 with: 7 with: 11. self ff: 2 with: 3 with: 4 with: 1 with: 8 with: 19. self ff: 1 with: 2 with: 3 with: 4 with: 9 with: 3. self ff: 4 with: 1 with: 2 with: 3 with: 10 with: 7. self ff: 3 with: 4 with: 1 with: 2 with: 11 with: 11. self ff: 2 with: 3 with: 4 with: 1 with: 12 with: 19. self ff: 1 with: 2 with: 3 with: 4 with: 13 with: 3. self ff: 4 with: 1 with: 2 with: 3 with: 14 with: 7. self ff: 3 with: 4 with: 1 with: 2 with: 15 with: 11. self ff: 2 with: 3 with: 4 with: 1 with: 16 with: 19. self gg: 1 with: 2 with: 3 with: 4 with: 1 with: 3. self gg: 4 with: 1 with: 2 with: 3 with: 5 with: 5. self gg: 3 with: 4 with: 1 with: 2 with: 9 with: 9. self gg: 2 with: 3 with: 4 with: 1 with: 13 with: 13. self gg: 1 with: 2 with: 3 with: 4 with: 2 with: 3. self gg: 4 with: 1 with: 2 with: 3 with: 6 with: 5. self gg: 3 with: 4 with: 1 with: 2 with: 10 with: 9. self gg: 2 with: 3 with: 4 with: 1 with: 14 with: 13. self gg: 1 with: 2 with: 3 with: 4 with: 3 with: 3. self gg: 4 with: 1 with: 2 with: 3 with: 7 with: 5. self gg: 3 with: 4 with: 1 with: 2 with: 11 with: 9. self gg: 2 with: 3 with: 4 with: 1 with: 15 with: 13. self gg: 1 with: 2 with: 3 with: 4 with: 4 with: 3. self gg: 4 with: 1 with: 2 with: 3 with: 8 with: 5. self gg: 3 with: 4 with: 1 with: 2 with: 12 with: 9. self gg: 2 with: 3 with: 4 with: 1 with: 16 with: 13. self hh: 1 with: 2 with: 3 with: 4 with: 1 with: 3. self hh: 4 with: 1 with: 2 with: 3 with: 9 with: 9. self hh: 3 with: 4 with: 1 with: 2 with: 5 with: 11. self hh: 2 with: 3 with: 4 with: 1 with: 13 with: 15. self hh: 1 with: 2 with: 3 with: 4 with: 3 with: 3. self hh: 4 with: 1 with: 2 with: 3 with: 11 with: 9. self hh: 3 with: 4 with: 1 with: 2 with: 7 with: 11. self hh: 2 with: 3 with: 4 with: 1 with: 15 with: 15. self hh: 1 with: 2 with: 3 with: 4 with: 2 with: 3. self hh: 4 with: 1 with: 2 with: 3 with: 10 with: 9. self hh: 3 with: 4 with: 1 with: 2 with: 6 with: 11. self hh: 2 with: 3 with: 4 with: 1 with: 14 with: 15. self hh: 1 with: 2 with: 3 with: 4 with: 4 with: 3. self hh: 4 with: 1 with: 2 with: 3 with: 12 with: 9. self hh: 3 with: 4 with: 1 with: 2 with: 8 with: 11. self hh: 2 with: 3 with: 4 with: 1 with: 16 with: 15. 1 to: 4 do: [ :i | state at: i put: ( ( ( state at: i ) +( savedState at: i ) ) bitAnd: 16rFFFFFFFF). savedState at: i put: 0. ].! ! !MD5 commentStamp: '' prior: 0! This implementation is provided for reverse compatibility reasons only. Do not use MD5 for new applications.! !MD5 methodsFor: 'output size' stamp: 'msh 6/16/2003 08:46'! outputSize ^16.! ! !MD5 methodsFor: 'private' stamp: 'msh 6/16/2003 08:45'! bufferConvert "Convert the contents of the byte array byteBuffer into the word array wordBuffer. " | j | 1 to: 16 do: [:i | j _ i - 1 * 4 + 1. wordBuffer at: i put: ((((byteBuffer at: j) bitOr: (byteBuffer at: 1 + j) << 8) bitOr: (byteBuffer at: 2 + j) << 16) bitOr: (byteBuffer at: 3 + j) << 24)]! ! !MD5 methodsFor: 'private' stamp: 'msh 6/16/2003 11:05'! ff: a with: b with: c with: d with: x with: s with: ac | t | t _ ( T at: ac ) + (wordBuffer at: x) + (state at: a) + (((state at: b) bitAnd: (state at: c)) bitOr: ((state at: b) bitInvert bitAnd: (state at: d))). state at: a put: ((self leftRotate: (t bitAnd: 16rFFFFFFFF) by: s) bitAnd: 16rFFFFFFFF). t _ 0. state at: a put: ( ( (state at: a) + (state at: b) ) bitAnd: 16rFFFFFFFF ).! ! !MD5 methodsFor: 'private' stamp: 'msh 6/16/2003 11:05'! gg: a with: b with: c with: d with: x with: s with: ac | t | t _ ( T at: ac ) + (wordBuffer at: x) + (state at: a) + (((state at: b) bitAnd: (state at: d)) bitOr: ((state at: c) bitAnd: (state at: d) bitInvert)). state at: a put: ((self leftRotate: (t bitAnd: 16rFFFFFFFF) by: s) bitAnd: 16rFFFFFFFF). t _ 0. state at: a put: ( ( (state at: a) + (state at: b) ) bitAnd: 16rFFFFFFFF ).! ! !MD5 methodsFor: 'private' stamp: 'msh 6/16/2003 11:05'! hh: a with: b with: c with: d with: x with: s with: ac | t | t _ ( T at: ac ) + (wordBuffer at: x) + (state at: a) + (((state at: b) bitXor: (state at: c)) bitXor: (state at: d)). state at: a put: ((self leftRotate: (t bitAnd: 16rFFFFFFFF) by: s) bitAnd: 16rFFFFFFFF). t _ 0. state at: a put: ( ( (state at: a) + (state at: b) ) bitAnd: 16rFFFFFFFF ).! ! !MD5 methodsFor: 'private' stamp: 'msh 6/16/2003 11:05'! ii: a with: b with: c with: d with: x with: s with: ac | t | t _ ( T at: ac ) + (wordBuffer at: x) + (state at: a) + ((state at: c) bitXor: ((state at: b) bitOr: (state at: d) bitInvert)). state at: a put: ((self leftRotate: (t bitAnd: 16rFFFFFFFF) by: s) bitAnd: 16rFFFFFFFF). t _ 0. state at: a put: ( ( (state at: a) + (state at: b) ) bitAnd: 16rFFFFFFFF ).! ! !MD5 methodsFor: 'private' stamp: 'msh 11/7/2005 01:46'! initialize "this method is evoked once by the new method. Do not call this method to initialize" "an instance of this class, call reinitialize instead." bitCount _ 0. byteBuffer _ ByteArray new: 64. byteCount _ 0. savedState _ Array new: 4. state _ Array new: 4. state at: 1 put: 16r67452301. state at: 2 put: 16rEFCDAB89. state at: 3 put: 16r98BADCFE. state at: 4 put: 16r10325476. wordBuffer _ Array new: 16.! ! !MD5 methodsFor: 'private' stamp: 'msh 6/16/2003 17:15'! transform self bufferConvert. 1 to: 4 do: [ :i | savedState at: i put: ( state at: i ). ]. self ff: 1 with: 2 with: 3 with: 4 with: 1 with: 7 with: 1. self ff: 4 with: 1 with: 2 with: 3 with: 2 with: 12 with: 2. self ff: 3 with: 4 with: 1 with: 2 with: 3 with: 17 with: 3. self ff: 2 with: 3 with: 4 with: 1 with: 4 with: 22 with: 4. self ff: 1 with: 2 with: 3 with: 4 with: 5 with: 7 with: 5. self ff: 4 with: 1 with: 2 with: 3 with: 6 with: 12 with: 6. self ff: 3 with: 4 with: 1 with: 2 with: 7 with: 17 with: 7. self ff: 2 with: 3 with: 4 with: 1 with: 8 with: 22 with: 8. self ff: 1 with: 2 with: 3 with: 4 with: 9 with: 7 with: 9. self ff: 4 with: 1 with: 2 with: 3 with: 10 with: 12 with: 10. self ff: 3 with: 4 with: 1 with: 2 with: 11 with: 17 with: 11. self ff: 2 with: 3 with: 4 with: 1 with: 12 with: 22 with: 12. self ff: 1 with: 2 with: 3 with: 4 with: 13 with: 7 with: 13. self ff: 4 with: 1 with: 2 with: 3 with: 14 with: 12 with: 14. self ff: 3 with: 4 with: 1 with: 2 with: 15 with: 17 with: 15. self ff: 2 with: 3 with: 4 with: 1 with: 16 with: 22 with: 16. self gg: 1 with: 2 with: 3 with: 4 with: 2 with: 5 with: 17. self gg: 4 with: 1 with: 2 with: 3 with: 7 with: 9 with: 18. self gg: 3 with: 4 with: 1 with: 2 with: 12 with: 14 with: 19. self gg: 2 with: 3 with: 4 with: 1 with: 1 with: 20 with: 20. self gg: 1 with: 2 with: 3 with: 4 with: 6 with: 5 with: 21. self gg: 4 with: 1 with: 2 with: 3 with: 11 with: 9 with: 22. self gg: 3 with: 4 with: 1 with: 2 with: 16 with: 14 with: 23. self gg: 2 with: 3 with: 4 with: 1 with: 5 with: 20 with: 24. self gg: 1 with: 2 with: 3 with: 4 with: 10 with: 5 with: 25. self gg: 4 with: 1 with: 2 with: 3 with: 15 with: 9 with: 26. self gg: 3 with: 4 with: 1 with: 2 with: 4 with: 14 with: 27. self gg: 2 with: 3 with: 4 with: 1 with: 9 with: 20 with: 28. self gg: 1 with: 2 with: 3 with: 4 with: 14 with: 5 with: 29. self gg: 4 with: 1 with: 2 with: 3 with: 3 with: 9 with: 30. self gg: 3 with: 4 with: 1 with: 2 with: 8 with: 14 with: 31. self gg: 2 with: 3 with: 4 with: 1 with: 13 with: 20 with: 32. self hh: 1 with: 2 with: 3 with: 4 with: 6 with: 4 with: 33. self hh: 4 with: 1 with: 2 with: 3 with: 9 with: 11 with: 34. self hh: 3 with: 4 with: 1 with: 2 with: 12 with: 16 with: 35. self hh: 2 with: 3 with: 4 with: 1 with: 15 with: 23 with: 36. self hh: 1 with: 2 with: 3 with: 4 with: 2 with: 4 with: 37. self hh: 4 with: 1 with: 2 with: 3 with: 5 with: 11 with: 38. self hh: 3 with: 4 with: 1 with: 2 with: 8 with: 16 with: 39. self hh: 2 with: 3 with: 4 with: 1 with: 11 with: 23 with: 40. self hh: 1 with: 2 with: 3 with: 4 with: 14 with: 4 with: 41. self hh: 4 with: 1 with: 2 with: 3 with: 1 with: 11 with: 42. self hh: 3 with: 4 with: 1 with: 2 with: 4 with: 16 with: 43. self hh: 2 with: 3 with: 4 with: 1 with: 7 with: 23 with: 44. self hh: 1 with: 2 with: 3 with: 4 with: 10 with: 4 with: 45. self hh: 4 with: 1 with: 2 with: 3 with: 13 with: 11 with: 46. self hh: 3 with: 4 with: 1 with: 2 with: 16 with: 16 with: 47. self hh: 2 with: 3 with: 4 with: 1 with: 3 with: 23 with: 48. self ii: 1 with: 2 with: 3 with: 4 with: 1 with: 6 with: 49. self ii: 4 with: 1 with: 2 with: 3 with: 8 with: 10 with: 50. self ii: 3 with: 4 with: 1 with: 2 with: 15 with: 15 with: 51. self ii: 2 with: 3 with: 4 with: 1 with: 6 with: 21 with: 52. self ii: 1 with: 2 with: 3 with: 4 with: 13 with: 6 with: 53. self ii: 4 with: 1 with: 2 with: 3 with: 4 with: 10 with: 54. self ii: 3 with: 4 with: 1 with: 2 with: 11 with: 15 with: 55. self ii: 2 with: 3 with: 4 with: 1 with: 2 with: 21 with: 56. self ii: 1 with: 2 with: 3 with: 4 with: 9 with: 6 with: 57. self ii: 4 with: 1 with: 2 with: 3 with: 16 with: 10 with: 58. self ii: 3 with: 4 with: 1 with: 2 with: 7 with: 15 with: 59. self ii: 2 with: 3 with: 4 with: 1 with: 14 with: 21 with: 60. self ii: 1 with: 2 with: 3 with: 4 with: 5 with: 6 with: 61. self ii: 4 with: 1 with: 2 with: 3 with: 12 with: 10 with: 62. self ii: 3 with: 4 with: 1 with: 2 with: 3 with: 15 with: 63. self ii: 2 with: 3 with: 4 with: 1 with: 10 with: 21 with: 64. 1 to: 4 do: [ :i | state at: i put: (((state at: i) + (savedState at: i)) bitAnd: 16rFFFFFFFF). savedState at: i put: 0. ].! ! !MD5 methodsFor: 'digesting' stamp: 'msh 6/16/2003 13:54'! digest: aByteArray at: anIndex | currentBitCount mask | currentBitCount _ bitCount. "append padding" ( byteCount < 56 ) ifTrue: [ self update: Padding at: 1 count: ( 56 - byteCount ). ] ifFalse: [ self update: Padding at: 1 count: ( 121 - byteCount ). ]. "add bit count" mask _ 16rFF00000000000000. 1 to: 8 do: [ :i | byteBuffer at: ( 65 - i ) put: ( (currentBitCount bitAnd: mask) >> ( (8 - i) * 8 ) ). mask _ mask >> 8. ]. "transform the final buffer" self transform. "write state to output" aByteArray at: (3 + anIndex) put: ( ( ( state at: 1 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (2 + anIndex) put: ( ( ( state at: 1 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (1 + anIndex) put: ( ( ( state at: 1 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (anIndex) put: ( ( state at: 1 ) bitAnd: 16rFF ). aByteArray at: (7 + anIndex) put: ( ( ( state at: 2 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (6 + anIndex) put: ( ( ( state at: 2 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (5 + anIndex) put: ( ( ( state at: 2 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (4 + anIndex) put: ( ( state at: 2 ) bitAnd: 16rFF ). aByteArray at: (11 + anIndex) put: ( ( ( state at: 3 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (10 + anIndex) put: ( ( ( state at: 3 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (9 + anIndex) put: ( ( ( state at: 3 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (8 + anIndex) put: ( ( state at: 3 ) bitAnd: 16rFF ). aByteArray at: (15 + anIndex) put: ( ( ( state at: 4 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (14 + anIndex) put: ( ( ( state at: 4 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (13 + anIndex) put: ( ( ( state at: 4 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (12 + anIndex) put: ( ( state at: 4 ) bitAnd: 16rFF ).! ! !MD5 methodsFor: 'digesting' stamp: 'msh 6/16/2003 09:24'! reinitialize bitCount _ 0. 1 to: (byteBuffer size) do: [ :i | byteBuffer at: i put: 0 ]. byteCount _ 0. 1 to: (savedState size) do: [ :i | savedState at: i put: 0 ]. state at: 1 put: 16r67452301. state at: 2 put: 16rEFCDAB89. state at: 3 put: 16r98BADCFE. state at: 4 put: 16r10325476. 1 to: (wordBuffer size) do: [ :i | wordBuffer at: i put: 0 ].! ! !MD5 methodsFor: 'digesting' stamp: 'msh 6/16/2003 17:15'! update: aByteArray at: anIndex count: aCount anIndex to: (anIndex + aCount - 1) do: [ :i | byteCount _ byteCount + 1. bitCount _ bitCount + 8. ( byteCount > 64 ) ifTrue: [ byteCount _ 1. self transform. ]. byteBuffer at: byteCount put: ( aByteArray at: i ). ].! ! !MessageDigest class methodsFor: 'class initialization' stamp: 'msh 6/16/2003 23:46'! initialize Padding _ #(128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ).! ! !MD2 class methodsFor: 'class initialization' stamp: 'msh 6/16/2003 23:40'! initialize "Initialize the Sbox and MD2Padding class variables." Sbox _ #( 16r29 16r2E 16r43 16rC9 16rA2 16rD8 16r7C 16r01 16r3D 16r36 16r54 16rA1 16rEC 16rF0 16r06 16r13 16r62 16rA7 16r05 16rF3 16rC0 16rC7 16r73 16r8C 16r98 16r93 16r2B 16rD9 16rBC 16r4C 16r82 16rCA 16r1E 16r9B 16r57 16r3C 16rFD 16rD4 16rE0 16r16 16r67 16r42 16r6F 16r18 16r8A 16r17 16rE5 16r12 16rBE 16r4E 16rC4 16rD6 16rDA 16r9E 16rDE 16r49 16rA0 16rFB 16rF5 16r8E 16rBB 16r2F 16rEE 16r7A 16rA9 16r68 16r79 16r91 16r15 16rB2 16r07 16r3F 16r94 16rC2 16r10 16r89 16r0B 16r22 16r5F 16r21 16r80 16r7F 16r5D 16r9A 16r5A 16r90 16r32 16r27 16r35 16r3E 16rCC 16rE7 16rBF 16rF7 16r97 16r03 16rFF 16r19 16r30 16rB3 16r48 16rA5 16rB5 16rD1 16rD7 16r5E 16r92 16r2A 16rAC 16r56 16rAA 16rC6 16r4F 16rB8 16r38 16rD2 16r96 16rA4 16r7D 16rB6 16r76 16rFC 16r6B 16rE2 16r9C 16r74 16r04 16rF1 16r45 16r9D 16r70 16r59 16r64 16r71 16r87 16r20 16r86 16r5B 16rCF 16r65 16rE6 16r2D 16rA8 16r02 16r1B 16r60 16r25 16rAD 16rAE 16rB0 16rB9 16rF6 16r1C 16r46 16r61 16r69 16r34 16r40 16r7E 16r0F 16r55 16r47 16rA3 16r23 16rDD 16r51 16rAF 16r3A 16rC3 16r5C 16rF9 16rCE 16rBA 16rC5 16rEA 16r26 16r2C 16r53 16r0D 16r6E 16r85 16r28 16r84 16r09 16rD3 16rDF 16rCD 16rF4 16r41 16r81 16r4D 16r52 16r6A 16rDC 16r37 16rC8 16r6C 16rC1 16rAB 16rFA 16r24 16rE1 16r7B 16r08 16r0C 16rBD 16rB1 16r4A 16r78 16r88 16r95 16r8B 16rE3 16r63 16rE8 16r6D 16rE9 16rCB 16rD5 16rFE 16r3B 16r00 16r1D 16r39 16rF2 16rEF 16rB7 16r0E 16r66 16r58 16rD0 16rE4 16rA6 16r77 16r72 16rF8 16rEB 16r75 16r4B 16r0A 16r31 16r44 16r50 16rB4 16r8F 16rED 16r1F 16r1A 16rDB 16r99 16r8D 16r33 16r9F 16r11 16r83 16r14 ). MD2Padding _ #( #( 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 ) #( 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 ) #( 14 14 14 14 14 14 14 14 14 14 14 14 14 14 ) #( 13 13 13 13 13 13 13 13 13 13 13 13 13 ) #( 12 12 12 12 12 12 12 12 12 12 12 12 ) #( 11 11 11 11 11 11 11 11 11 11 11 ) #( 10 10 10 10 10 10 10 10 10 10 ) #( 9 9 9 9 9 9 9 9 9 ) #( 8 8 8 8 8 8 8 8 ) #( 7 7 7 7 7 7 7 ) #( 6 6 6 6 6 6 ) #( 5 5 5 5 5 ) #( 4 4 4 4 ) #( 3 3 3 ) #( 2 2 ) #( 1 ) ). ! ! !MD2 class methodsFor: 'instance creation' stamp: 'msh 6/13/2003 01:02'! new ^super new initialize.! ! !MD4 class methodsFor: 'instance creation' stamp: 'msh 6/13/2003 01:23'! new ^super new initialize.! ! !MD5 class methodsFor: 'instance creation' stamp: 'msh 6/16/2003 08:37'! new ^super new initialize.! ! !MD5 class methodsFor: 'class initialization' stamp: 'msh 6/16/2003 22:28'! initialize T _ #( 16rD76AA478 16rE8C7B756 16r242070DB 16rC1BDCEEE 16rF57C0FAF 16r4787C62A 16rA8304613 16rFD469501 16r698098D8 16r8B44F7AF 16rFFFF5BB1 16r895CD7BE 16r6B901122 16rFD987193 16rA679438E 16r49B40821 16rF61E2562 16rC040B340 16r265E5A51 16rE9B6C7AA 16rD62F105D 16r2441453 16rD8A1E681 16rE7D3FBC8 16r21E1CDE6 16rC33707D6 16rF4D50D87 16r455A14ED 16rA9E3E905 16rFCEFA3F8 16r676F02D9 16r8D2A4C8A 16rFFFA3942 16r8771F681 16r6D9D6122 16rFDE5380C 16rA4BEEA44 16r4BDECFA9 16rF6BB4B60 16rBEBFBC70 16r289B7EC6 16rEAA127FA 16rD4EF3085 16r4881D05 16rD9D4D039 16rE6DB99E5 16r1FA27CF8 16rC4AC5665 16rF4292244 16r432AFF97 16rAB9423A7 16rFC93A039 16r655B59C3 16r8F0CCC92 16rFFEFF47D 16r85845DD1 16r6FA87E4F 16rFE2CE6E0 16rA3014314 16r4E0811A1 16rF7537E82 16rBD3AF235 16r2AD7D2BB 16rEB86D391 ). ! ! !MetaSuperSendLiteralMarker commentStamp: 'crl 2/12/2004 22:22' prior: 0! ' Each of my instances indicates, to a remote system reading a serialized CompiledMethod, a method literal which refers to the method-class of a metaclass super-send method. Author: Craig Latta ! !MethodDescription commentStamp: 'crl 2/12/2004 22:07' prior: 0! ' Each of my instances describes a method in the local system for which some Author has asserted authorship, or which is associated with a Module. Author: Craig Latta ! !MethodID commentStamp: 'crl 2/12/2004 22:12' prior: 0! ' Each of my instances identifies, using a sequence of bytes suitable for network transmisison, a particular version of a CompiledMethod installed at some selector in some Behavior's method dictionary, written by some Author. Author: Craig Latta ! !MethodServer commentStamp: 'crl 2/12/2004 21:56' prior: 0! ' Each of my instances knows how to serve CompiledMethods from this system to a remote one. Typically, there's only one active instance at a time. Author: Craig Latta This class has not yet been commented.! !Module commentStamp: 'crl 2/12/2004 22:12' prior: 0! ' Each of my instances identifies a set of methods which, when active, provide one or more related features. "Method" here refers specifically to a particular compiled method, associated with a class identifier and selector. Each method in the system has an identifier unique to its class. Each class identifier is universally unique. Author: Craig Latta ! !ModuleServer commentStamp: 'crl 2/12/2004 22:01' prior: 0! ' Each of my instances services a request for module synchronization with a remote system. Author: Craig Latta ! !NegativeManifest commentStamp: 'crl 2/12/2004 22:25' prior: 0! ' Each of my instances compactly describes the absence of elements in a collection. These instances are used in Module synchronization, in order for a remote system to describe which elements of a set fulfill some criterion with a minimum of network traffic. Author: Craig Latta ! !NetMessage commentStamp: 'crl 2/13/2004 14:09' prior: 0! ' I am an abstract Class. Instances of my concrete subclasses are byte-oriented messages (usually composed of text characters). They're dressed up with little bits of meta-information to guide them in their journey from here to there, and to provide a semantic framework once they arrive. Each instance may be treated as a stream over a message body. Author: Craig Latta ! !HTTPMessage commentStamp: 'crl 2/13/2004 14:11' prior: 0! ' Each of my instances represents an HTTP/1.1 message, as defined in RFC 2616. Authors: asparagi Craig Latta ! !HTTPRequest commentStamp: 'crl 2/13/2004 14:11' prior: 0! ' Each of my instances represents a request, via the HTTP protocol, for a resource. class instance variables: requestMethods a Set of upper case Strings which represent the HTTP methods my instances know how to handle instance variables: requestMethod a String (one of those in requestMethods) indicating which particular method this request is using uri a Url identifying the requested resource httpVersion a String indicating which HTTP version this request is using Authors: asparagi Craig Latta ! !HTTPResponse commentStamp: 'crl 2/13/2004 14:12' prior: 0! ' Each of my instances represents a resource, with decoration appropriate for transmitting it via the HTTP protocol. Authors: asparagi Craig Latta ! !NetResource commentStamp: 'crl 2/13/2004 12:29' prior: 0! ' I am an abstract Class. Instances of my concrete subclasses represent network resources. Said resources are distinguished from others by their potentially unbounded content length. instance variables: readingSemaphore a Semaphore used for suspending the Process of a sender which wants to read from an instance writingSemaphore a Semaphore used for suspending the Process of a sender which wants to write to an instance Author: Craig Latta ! !NetStream commentStamp: 'crl 2/13/2004 14:04' prior: 0! ' Each of my instances provides streaming access to asynchronous external resources. I provide support for buffering read and written elements. Author: Craig Latta ! !ObjectTransferCorrespondent commentStamp: 'crl 2/12/2004 22:36' prior: 0! ' I am an abstract Class. Each instance of my concrete subclasses is capable of reading and writing objects over a network connection. Author: Craig Latta ! !MethodClient commentStamp: 'crl 2/12/2004 21:55' prior: 0! ' Each of my instances knows how to transfer CompiledMethods from a remote system to this one. Typically, there is only one active instance at a time. Author: Craig Latta ! !Other commentStamp: 'crl 2/12/2004 22:38' prior: 0! ' Each of my instances respresents an object in another object memory, reachable via a NetStream. Any message sent to one of my instances (except for the five messages needed for forwarding) is forwarded to the remote object, and another Other is answered. This forwarding coverage is complete; even messages normally handled by the virtual machine, or resolved in the method cache, are forwarded. As a result, Others can be tricky to handle with traditional development tools; proceed with caution. Also, I won't compile any more instance methods that send messages to self, since the concept is generally meaningless for my instances. Author: Craig Latta ! !Password class methodsFor: 'accessing'! at: aKey "return the shared secret referenced by aKey. In other words, we created a password for" "the Password class to manage. So instead of holding a password, the application class holds" "a reference to the password. That reference is a simple descriptive string like:" "celeste:account:msh@cryptonomicon.net" "This is an example of how Celeste might choose to represent a password managed by the" "Password class." ^ ( self passwords ) at: aKey .! ! !Password class methodsFor: 'accessing'! at: aKey put: aValue ^ ( self passwords ) at: aKey put: aValue.! ! !Password class methodsFor: 'private' stamp: 'il prior: 34095788!! '! fileInPasswords | passwordFileStream | passwordFileStream _ FileStream oldFileNamed: (self vaultFileName). self fileInPasswordsFromStream: passwordFileStream. passwordFileStream close. ! ! !Password class methodsFor: 'private' stamp: 'il prior: 34121901!! '! fileInPasswordsFromStream: aStream | dcryptor encryptedStream state currentLine currentChar tokens | dcryptor _ ( ARC4 new ) initialize: ( self masterKey). encryptedStream _ EncryptedStream on: aStream with: dcryptor. state _ #FirstLine. currentLine _ ''. [ encryptedStream atEnd ] whileFalse: [ "Todo: This is probably bad." currentChar _ ( ( encryptedStream next ) asCharacter ). ( ( currentChar asInteger ) = 13 ) ifFalse: [ currentLine _ currentLine , ( currentChar ) asString. ] ifTrue: [ ( state = #FirstLine ) ifTrue: [ ( currentLine = (self magicCookie) ) ifTrue: [ state _ #NotFirstLine. ] ] ifFalse: [ tokens _ currentLine findTokens: ' '. (self passwords) at: (tokens at: 1) put: (tokens at: 2). ]. currentLine _ ''. ]. ]. encryptedStream close. dcryptor clearSensitiveData.! ! !Password class methodsFor: 'private' stamp: 'il prior: 34096052!! '! flushPasswordCache "write the password cache back out to the vault file." | passwordFileStream ncryptor | ncryptor _ ( ARC4 new) initialize: ( self masterKey ). passwordFileStream _ EncryptedStream on: ( FileStream newFileNamed: (self vaultFileName) ) with: ncryptor. passwordFileStream nextPutAll: (self magicCookie); cr. ( ( self passwords ) keys ) do: [ :current | passwordFileStream nextPutAll: current; nextPutAll: ' '; nextPutAll: ( self at: current ); cr. ].! ! !Password class methodsFor: 'private' stamp: 'il prior: 34087075!! '! magicCookie "this is such a BAD idea. You really don't want to have magic cookies at the front" "of files encrypted with vernam ciphers." ^ '31337MagicCookie' .! ! !Password class methodsFor: 'private' stamp: 'il prior: 34093073!! '! masterKey | passphrase | ( MasterKey isNil ) ifTrue: [ passphrase _ Preferences secretVaultPassword. passphrase ifNil: [ passphrase _ FillInTheBlank request: 'Vault Master Password?'. ]. self setMasterKeyFromString: passphrase. ]. ^ MasterKey .! ! !Password class methodsFor: 'private' stamp: 'msh 11/7/2005 15:48'! passwords "Return a reference to the Passwords dictionary if it is non-nil. If it is nil, it means we" "haven't read our passwords in from the vault." "note that this is a private method. If you want to access a particular password, use the" "#at: and #at:put: methods." ( Passwords isNil ) ifTrue: [ Passwords _ Dictionary new. self fileInPasswords. ]. ^ Passwords .! ! !Password class methodsFor: 'private' stamp: 'il prior: 34073573!! '! setMasterKeyFromString: aString | pbe | self clearMasterKey. pbe _ ( PasswordBasedEncryptor new ) password: aString; salt: #( 8 3 4 2 5 6 7 4 8 6 4 2 3 4 5 6 7 8 9 0 ); iteration: 50. MasterKey _ pbe pbkdf1. pbe clearSensitiveData. 1 to: ( aString size ) do: [ :current | aString at: current put: $$ ].! ! !Password class methodsFor: 'private'! vaultFileName | fileName | fileName _ Preferences secretVaultFileName. fileName ifNil: [ fileName _ 'svault.bin'. ]. ^ fileName .! ! !Password class methodsFor: 'eschatology' stamp: 'il prior: 34061650!! '! shutDown self flushPasswordCache; clearSensitiveData.! ! !Password class methodsFor: 'sensitive data' stamp: 'il prior: 34072012!! '! clearMasterKey MasterKey ifNotNil: [ 1 to: (MasterKey size) do: [ :current | MasterKey at: current put: 0. ]. ]. MasterKey _ nil.! ! !Password class methodsFor: 'sensitive data' stamp: 'msh 11/7/2005 12:01'! clearPassword: aKey "Overwrite the password referenced by the value aKey, then remove it from the passwords" "dictionary." | theString passwordDictionary | passwordDictionary _ self passwords. theString _ ( passwordDictionary at: aKey ). 1 to: ( theString size ) do: [ :current | theString at: current put: $$. ]. passwordDictionary removeKey: aKey.! ! !Password class methodsFor: 'sensitive data' stamp: 'il prior: 34072486!! '! clearSensitiveData "Overwrite passwords in the Passwords dictionary, then remove the Association." ( ( self passwords ) keys ) do: [ :current | self clearPassword: current. ]. self clearMasterKey. Passwords _ nil.! ! !PasswordBasedEncryptor commentStamp: '' prior: 0! This class derives encryption or message authentication keys from passwords according to the alogrithm(s) provided in PKCS#5 v2.0. The PKCS#5 spec describes two functions whose inputs are a password, a salt, and an iteration count and whose output is a "derived key." The two functions: PBKDF1 and PBKDF2 are implemented as messages to an instance of this class. The former is recommended only for compatibility with previous applications while the latter is recommended for new applications. Like other classes in this package, after you have used it, send it the #clearSensitiveData message to erase remnants of sensitive bits of data (like the password). Here's an example of the use of this function: | encryptionKey pbe | pbe _ ( PasswordBasedEncryptor new ) password: 'you can have a very long passphrase if you like'; salt: #( 8 3 4 2 5 6 7 4 8 6 4 2 3 4 5 6 7 8 9 0 ); iteration: 1000. encryptionKey _ pbe pbkdf1. pbe clearSensitiveData. encryptionKey inspect Things to note here include: * You can pass a string or a byte array as a password. It doesn't matter. * The salt is some "randomly" chosen string of bytes, it's probably important to note that the salt does not have to be secret. * Though the salt doesn't have to be secret, it can't be guessable, so the example above is "wrong" in that regard. * You can have any iteration count you like. The spec currently recommends at least 1000. * The code was intended to be understandable, not efficient. And it shows. Don't freak out if it takes a little longer than you think it should. There's another way to derive a key which allows you to pick the type of hash function you want to use: | encryptionKey pbe | pbe _ ( PasswordBasedEncryptor new ) password: 'you can have a very long passphrase if you like'; salt: #( 8 3 4 2 5 6 7 4 8 6 4 2 3 4 5 6 7 8 9 0 ); iteration: 1000. encryptionKey _ pbe pbkdf1withDigestor( SHA256 new ). pbe clearSensitiveData. encryptionKey inspect This is interesting because it allows you to pick a message digest code with a larger digest size. This is useful if the first form does not generate enough bits for your requirements. The first form uses a SHA1 function by default which generates 160 bits of output; not especially useful if you're trying to derive a key for an cipher that uses 256 bit keys. ! !PasswordBasedEncryptor methodsFor: 'key derivation' stamp: 'msh 5/4/2005 18:43'! pbkdf1 "returns a byte array containing derived key." ^ self pbkdf1withDigestor: ( SHA1 new ) .! ! !PasswordBasedEncryptor methodsFor: 'key derivation' stamp: 'msh 5/4/2005 18:05'! pbkdf1withDigestor: aDigestor "returns a byte array containing derived key using the given digest object." | derivedKey | derivedKey _ ByteArray new: (aDigestor outputSize). self pbkdf1withDigestor: aDigestor on: derivedKey atOffset: 1 withLength: ( derivedKey size ). ^ derivedKey . ! ! !PasswordBasedEncryptor methodsFor: 'key derivation' stamp: 'msh 5/4/2005 18:42'! pbkdf1withDigestor: aDigestor on: outputArray atOffset: anIndex withLength: length "returns a byte array containing derived key using the given digest object." | initial passwordArray previous current | initial _ ByteArray new: (password size + salt size). passwordArray _ password asByteArray. 1 to: ( passwordArray size ) do: [ :index | initial at: index put: ( passwordArray at: index ). passwordArray at: index put: 0. ]. 1 to: ( salt size ) do: [ :index | initial at: ( index + ( passwordArray size ) ) put: ( salt at: index ). ]. aDigestor initialize; update: initial. current _ aDigestor digest. 1 to: ( initial size ) do: [ :index | initial at: index put: 0. ]. previous _ ByteArray new: ( current size ). 2 to: iteration do: [ :count | 1 to: ( current size ) do: [ :index | previous at: index put: (current at: index). ]. aDigestor initialize; update: previous; digest: current at: 1. ]. 1 to: ( current size ) do: [ :index | ( index <= length ) ifTrue: [ outputArray at: ( index + anIndex - 1) put: (current at: index). ]. previous at: index put: 0. current at: index put: 0. ]. ! ! !PasswordBasedEncryptor methodsFor: 'accessing' stamp: 'msh 5/4/2005 17:55'! iteration: anInteger iteration _ anInteger.! ! !PasswordBasedEncryptor methodsFor: 'accessing' stamp: 'msh 5/4/2005 18:55'! password: aStringOrArray password _ aStringOrArray asByteArray.! ! !PasswordBasedEncryptor methodsFor: 'accessing' stamp: 'msh 5/4/2005 17:55'! salt: anArray salt _ anArray.! ! !PasswordBasedEncryptor methodsFor: 'sensitive data' stamp: 'msh 5/4/2005 17:54'! clearSensitiveData ( password respondsTo: #clearSensitiveData ) ifTrue: [ password clearSensitiveData. ] ifFalse: [ 1 to: ( password size ) do: [ :index | password at: index put: 0. ]. ]. ! ! !PathSegmentCollection commentStamp: 'crl 2/13/2004 14:14' prior: 0! ' My instances represent a path through a hierarchy. They are used in hierarchical URIs. Author: asparagi! !PositiveManifest commentStamp: 'crl 2/12/2004 22:25' prior: 0! ' Each of my instances compactly describes the existence of elements in a collection. These instances are used in Module synchronization, in order for a remote system to describe which elements of a set fulfill some criterion with a minimum of network traffic. Author: Craig Latta ! !Preferences class methodsFor: 'as yet unclassified' stamp: 'il prior: 0!! '! initialize FlagDictionary _ Dictionary new. SecretVaultFileName _ 'svault.bin'. self chooseInitialSettings! ! !Preferences class methodsFor: 'as yet unclassified'! secretVaultFileName ^ SecretVaultFileName .! ! !Preferences class methodsFor: 'as yet unclassified'! secretVaultFileName: aString SecretVaultFileName _ aString.! ! !Preferences class methodsFor: 'as yet unclassified' stamp: 'il prior: 34061741!! '! secretVaultPassword "For the love of everything dear, please, please, please don't do what you're about to do." "Don't embed your vault password in the image itself!!" ^ SecretVaultPassword .! ! !Preferences class methodsFor: 'as yet unclassified' stamp: 'il prior: 34061968!! '! secretVaultPassword: aString "For the love of everything dear, please, please, please don't do what you're about to do." "Don't embed your vault password in the image itself!!" SecretVaultPassword _ aString.! ! !RegisteredAuthority commentStamp: 'crl 2/13/2004 14:14' prior: 0! ' My instances identify the authority of a URI, using a registry. instance variables: - name a String representing the name of this authority Author: asparagi! !RemoteClosure commentStamp: 'crl 2/12/2004 23:06' prior: 0! ' Each of my instances represents a local block closure used in a message sent to a remote object. Author: Craig Latta ! !RemoteMessageDispatcher commentStamp: 'crl 2/12/2004 23:07' prior: 0! ' I am an abstract Class. Each instance of my concrete subclasses dispatches messages to objects in a remote system. Author: Craig Latta ! !Apprentice commentStamp: 'crl 2/12/2004 23:14' prior: 0! ' Each of my instances exposes the identities of itself and the local system dictionary to a Sorcerer running in a remote system. With this information, the Sorcerer may create Others (proxies) for those objects, and thereby send messages to any object it likes. An Apprentice also can perform various housekeeping tasks for the Sorcerer. There is typically only one Apprentice active in a system at a time. The system in which an Apprentice runs is typically a minimal headless snapshot; the Apprentice often represents the only convenient means for a human to send messages to the objects in its system. Author: Craig Latta ! !ModuleClient commentStamp: 'crl 2/12/2004 22:00' prior: 0! ' Each of my instances initiates module synchronization conversations with a remote system. Author: Craig Latta ! !SHA1 methodsFor: 'private' stamp: 'msh 6/17/2003 01:18'! bufferConvert "Convert the contents of the byte array byteBuffer into the word array wordBuffer. " | j | 1 to: 16 do: [:i | j _ i - 1 * 4 + 1. wordBuffer at: i put: ((((byteBuffer at: (3 +j) ) bitOr: (byteBuffer at: 2 + j) << 8) bitOr: (byteBuffer at: 1 + j) << 16) bitOr: (byteBuffer at: j) << 24)]! ! !SHA1 methodsFor: 'private' stamp: 'msh 6/17/2003 00:52'! ch ^ (((state at: 2) bitAnd: (state at: 3)) bitXor: (((state at: 2) bitInvert ) bitAnd: (state at: 4))) .! ! !SHA1 methodsFor: 'private' stamp: 'msh 11/7/2005 01:47'! initialize bitCount _ 0. byteBuffer _ ByteArray new: 64. byteCount _ 0. savedState _ Array new: 5. state _ Array new: 5. state at: 1 put: 16r67452301. state at: 2 put: 16rEFCDAB89. state at: 3 put: 16r98BADCFE. state at: 4 put: 16r10325476. state at: 5 put: 16rC3D2E1F0. wordBuffer _ Array new: 16. workBuffer _ Array new: 80.! ! !SHA1 methodsFor: 'private' stamp: 'msh 6/17/2003 00:55'! maj ^ ( ( ( ( state at: 2 ) bitAnd: ( state at: 3 ) ) bitXor: ( ( state at: 2 ) bitAnd: ( state at: 4 ) ) ) bitXor: ( ( state at: 3 ) bitAnd: ( state at: 4 ) ) ).! ! !SHA1 methodsFor: 'private' stamp: 'msh 6/17/2003 00:53'! parity ^ ( ( ( state at: 2 ) bitXor: ( state at: 3 ) ) bitXor: ( state at: 4 ) ).! ! !SHA1 methodsFor: 'private' stamp: 'msh 6/17/2003 01:31'! transform | t | self bufferConvert. 1 to: 16 do: [ :i | workBuffer at: i put: ( wordBuffer at: i ). ]. 17 to: 80 do: [ :i | workBuffer at: i put: ( ( self leftRotate: ( ( ( ( ( workBuffer at: ( i - 3 ) ) bitXor: ( workBuffer at: ( i - 8 ) ) ) bitXor: ( workBuffer at: ( i - 14) ) ) bitXor: ( workBuffer at: ( i - 16) ) ) ) by: 1 ) bitAnd: 16rFFFFFFFF ). ]. 1 to: 5 do: [ :i | savedState at: i put: ( state at: i ). ]. 1 to: 80 do: [ :i | t _ ( (self leftRotate: (state at: 1) by: 5 ) + (state at: 5) + (K at: i) + (workBuffer at: i) ) bitAnd: 16rFFFFFFFF. ( i between: 1 and: 20 ) ifTrue: [ t _ ( t + ( self ch ) ) bitAnd: 16rFFFFFFFF. ]. ( i between: 21 and: 40 ) ifTrue: [ t _ ( t + ( self parity ) ) bitAnd: 16rFFFFFFFF. ]. ( i between: 41 and: 60 ) ifTrue: [ t _ ( t + ( self maj ) ) bitAnd: 16rFFFFFFFF. ]. ( i between: 61 and: 80 ) ifTrue: [ t _ ( t + ( self parity ) ) bitAnd: 16rFFFFFFFF. ]. state at: 5 put: ( state at: 4 ). state at: 4 put: ( state at: 3 ). state at: 3 put: ( ( self leftRotate: (state at: 2) by: 30 ) bitAnd: 16rFFFFFFFF ). state at: 2 put: ( state at: 1 ). state at: 1 put: t. ]. 1 to: 5 do: [ :i | state at: i put: ( ( ( state at: i ) + ( savedState at: i ) ) bitAnd: 16rFFFFFFFF ). ].! ! !SHA1 methodsFor: 'output size' stamp: 'msh 6/17/2003 00:09'! outputSize ^20.! ! !SHA1 methodsFor: 'digesting' stamp: 'msh 6/17/2003 01:31'! digest: aByteArray at: anIndex | currentBitCount mask | currentBitCount _ bitCount. "append padding" ( byteCount < 56 ) ifTrue: [ self update: Padding at: 1 count: ( 56 - byteCount ). ] ifFalse: [ self update: Padding at: 1 count: ( 121 - byteCount ). ]. "add bit count" mask _ 16rFF00000000000000. 1 to: 8 do: [ :i | byteBuffer at: ( 56 + i ) put: ( (currentBitCount bitAnd: mask) >> ( (8 - i) * 8 ) ). mask _ mask >> 8. ]. "transform the final buffer" self transform. "write state to output" aByteArray at: (anIndex) put: ( ( ( state at: 1 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (1 + anIndex) put: ( ( ( state at: 1 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (2 + anIndex) put: ( ( ( state at: 1 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (3 + anIndex) put: ( ( state at: 1 ) bitAnd: 16rFF ). aByteArray at: (4 + anIndex) put: ( ( ( state at: 2 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (5 + anIndex) put: ( ( ( state at: 2 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (6 + anIndex) put: ( ( ( state at: 2 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (7 + anIndex) put: ( ( state at: 2 ) bitAnd: 16rFF ). aByteArray at: (8 + anIndex) put: ( ( ( state at: 3 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (9 + anIndex) put: ( ( ( state at: 3 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (10 + anIndex) put: ( ( ( state at: 3 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (11 + anIndex) put: ( ( state at: 3 ) bitAnd: 16rFF ). aByteArray at: (12 + anIndex) put: ( ( ( state at: 4 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (13 + anIndex) put: ( ( ( state at: 4 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (14 + anIndex) put: ( ( ( state at: 4 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (15 + anIndex) put: ( ( state at: 4 ) bitAnd: 16rFF ). aByteArray at: (16 + anIndex) put: ( ( ( state at: 5 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (17 + anIndex) put: ( ( ( state at: 5 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (18 + anIndex) put: ( ( ( state at: 5 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (19 + anIndex) put: ( ( state at: 5 ) bitAnd: 16rFF ).! ! !SHA1 methodsFor: 'digesting' stamp: 'msh 6/17/2003 00:10'! reinitialize bitCount _ 0. 1 to: (byteBuffer size) do: [ :i | byteBuffer at: i put: 0 ]. byteCount _ 0. 1 to: (savedState size) do: [ :i | savedState at: i put: 0 ]. state at: 1 put: 16r67452301. state at: 2 put: 16rEFCDAB89. state at: 3 put: 16r98BADCFE. state at: 4 put: 16r10325476. state at: 5 put: 16rC3D2E1F0. 1 to: (wordBuffer size) do: [ :i | wordBuffer at: i put: 0 ].! ! !SHA1 methodsFor: 'digesting' stamp: 'msh 6/17/2003 00:10'! update: aByteArray at: anIndex count: aCount anIndex to: (anIndex + aCount - 1) do: [ :i | byteCount _ byteCount + 1. bitCount _ bitCount + 8. ( byteCount > 64 ) ifTrue: [ byteCount _ 1. self transform. ]. byteBuffer at: byteCount put: ( aByteArray at: i ). ].! ! !SHA1 class methodsFor: 'instance creation' stamp: 'msh 6/17/2003 00:02'! new ^super new initialize.! ! !SHA1 class methodsFor: 'class initialization' stamp: 'msh 6/17/2003 00:34'! initialize K _ #( 16r5A827999 16r5A827999 16r5A827999 16r5A827999 16r5A827999 16r5A827999 16r5A827999 16r5A827999 16r5A827999 16r5A827999 16r5A827999 16r5A827999 16r5A827999 16r5A827999 16r5A827999 16r5A827999 16r5A827999 16r5A827999 16r5A827999 16r5A827999 16r6ED9EBA1 16r6ED9EBA1 16r6ED9EBA1 16r6ED9EBA1 16r6ED9EBA1 16r6ED9EBA1 16r6ED9EBA1 16r6ED9EBA1 16r6ED9EBA1 16r6ED9EBA1 16r6ED9EBA1 16r6ED9EBA1 16r6ED9EBA1 16r6ED9EBA1 16r6ED9EBA1 16r6ED9EBA1 16r6ED9EBA1 16r6ED9EBA1 16r6ED9EBA1 16r6ED9EBA1 16r8F1BBCDC 16r8F1BBCDC 16r8F1BBCDC 16r8F1BBCDC 16r8F1BBCDC 16r8F1BBCDC 16r8F1BBCDC 16r8F1BBCDC 16r8F1BBCDC 16r8F1BBCDC 16r8F1BBCDC 16r8F1BBCDC 16r8F1BBCDC 16r8F1BBCDC 16r8F1BBCDC 16r8F1BBCDC 16r8F1BBCDC 16r8F1BBCDC 16r8F1BBCDC 16r8F1BBCDC 16rCA62C1D6 16rCA62C1D6 16rCA62C1D6 16rCA62C1D6 16rCA62C1D6 16rCA62C1D6 16rCA62C1D6 16rCA62C1D6 16rCA62C1D6 16rCA62C1D6 16rCA62C1D6 16rCA62C1D6 16rCA62C1D6 16rCA62C1D6 16rCA62C1D6 16rCA62C1D6 16rCA62C1D6 16rCA62C1D6 16rCA62C1D6 16rCA62C1D6 ).! ! !SHA256 methodsFor: 'output size' stamp: 'msh 6/17/2003 02:29'! outputSize ^32.! ! !SHA256 methodsFor: 'digesting' stamp: 'msh 6/17/2003 01:57'! digest: aByteArray at: anIndex | currentBitCount mask | currentBitCount _ bitCount. "append padding" ( byteCount < 56 ) ifTrue: [ self update: Padding at: 1 count: ( 56 - byteCount ). ] ifFalse: [ self update: Padding at: 1 count: ( 121 - byteCount ). ]. "add bit count" mask _ 16rFF00000000000000. 1 to: 8 do: [ :i | byteBuffer at: ( 56 + i ) put: ( (currentBitCount bitAnd: mask) >> ( (8 - i) * 8 ) ). mask _ mask >> 8. ]. "transform the final buffer" self transform. "write state to output" aByteArray at: (anIndex) put: ( ( ( state at: 1 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (1 + anIndex) put: ( ( ( state at: 1 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (2 + anIndex) put: ( ( ( state at: 1 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (3 + anIndex) put: ( ( state at: 1 ) bitAnd: 16rFF ). aByteArray at: (4 + anIndex) put: ( ( ( state at: 2 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (5 + anIndex) put: ( ( ( state at: 2 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (6 + anIndex) put: ( ( ( state at: 2 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (7 + anIndex) put: ( ( state at: 2 ) bitAnd: 16rFF ). aByteArray at: (8 + anIndex) put: ( ( ( state at: 3 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (9 + anIndex) put: ( ( ( state at: 3 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (10 + anIndex) put: ( ( ( state at: 3 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (11 + anIndex) put: ( ( state at: 3 ) bitAnd: 16rFF ). aByteArray at: (12 + anIndex) put: ( ( ( state at: 4 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (13 + anIndex) put: ( ( ( state at: 4 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (14 + anIndex) put: ( ( ( state at: 4 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (15 + anIndex) put: ( ( state at: 4 ) bitAnd: 16rFF ). aByteArray at: (16 + anIndex) put: ( ( ( state at: 5 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (17 + anIndex) put: ( ( ( state at: 5 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (18 + anIndex) put: ( ( ( state at: 5 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (19 + anIndex) put: ( ( state at: 5 ) bitAnd: 16rFF ). aByteArray at: (20 + anIndex) put: ( ( ( state at: 6 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (21 + anIndex) put: ( ( ( state at: 6 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (22 + anIndex) put: ( ( ( state at: 6 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (23 + anIndex) put: ( ( state at: 6 ) bitAnd: 16rFF ). aByteArray at: (24 + anIndex) put: ( ( ( state at: 7 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (25 + anIndex) put: ( ( ( state at: 7 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (26 + anIndex) put: ( ( ( state at: 7 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (27 + anIndex) put: ( ( state at: 7 ) bitAnd: 16rFF ). aByteArray at: (28 + anIndex) put: ( ( ( state at: 8 ) bitAnd: 16rFF000000 ) >> 24 ). aByteArray at: (29 + anIndex) put: ( ( ( state at: 8 ) bitAnd: 16rFF0000 ) >> 16 ). aByteArray at: (30 + anIndex) put: ( ( ( state at: 8 ) bitAnd: 16rFF00 ) >> 8 ). aByteArray at: (31 + anIndex) put: ( ( state at: 8 ) bitAnd: 16rFF ).! ! !SHA256 methodsFor: 'digesting' stamp: 'msh 6/17/2003 02:27'! reinitialize bitCount _ 0. 1 to: (byteBuffer size) do: [ :i | byteBuffer at: i put: 0 ]. byteCount _ 0. 1 to: (savedState size) do: [ :i | savedState at: i put: 0 ]. state at: 1 put: 16r6A09E667. state at: 2 put: 16rBB67AE85. state at: 3 put: 16r3C6EF372. state at: 4 put: 16rA54FF53A. state at: 5 put: 16r510E527F. state at: 6 put: 16r9B05688C. state at: 7 put: 16r1F83D9AB. state at: 8 put: 16r5BE0CD19. 1 to: (wordBuffer size) do: [ :i | wordBuffer at: i put: 0 ].! ! !SHA256 methodsFor: 'digesting' stamp: 'msh 6/17/2003 02:01'! update: aByteArray at: anIndex count: aCount anIndex to: (anIndex + aCount - 1) do: [ :i | byteCount _ byteCount + 1. bitCount _ bitCount + 8. ( byteCount > 64 ) ifTrue: [ byteCount _ 1. self transform. ]. byteBuffer at: byteCount put: ( aByteArray at: i ). ].! ! !SHA256 methodsFor: 'private' stamp: 'msh 6/17/2003 02:02'! bufferConvert "Convert the contents of the byte array byteBuffer into the word array wordBuffer. " | j | 1 to: 16 do: [:i | j _ i - 1 * 4 + 1. wordBuffer at: i put: ((((byteBuffer at: (3 +j) ) bitOr: (byteBuffer at: 2 + j) << 8) bitOr: (byteBuffer at: 1 + j) << 16) bitOr: (byteBuffer at: j) << 24)]! ! !SHA256 methodsFor: 'private' stamp: 'msh 6/17/2003 02:08'! ch ^ (((state at: 5) bitAnd: (state at: 6)) bitXor: (((state at: 5) bitInvert ) bitAnd: (state at: 7))) .! ! !SHA256 methodsFor: 'private' stamp: 'msh 11/7/2005 01:47'! initialize bitCount _ 0. byteBuffer _ ByteArray new: 64. byteCount _ 0. savedState _ Array new: 8. state _ Array new: 8. state at: 1 put: 16r6A09E667. state at: 2 put: 16rBB67AE85. state at: 3 put: 16r3C6EF372. state at: 4 put: 16rA54FF53A. state at: 5 put: 16r510E527F. state at: 6 put: 16r9B05688C. state at: 7 put: 16r1F83D9AB. state at: 8 put: 16r5BE0CD19. wordBuffer _ Array new: 16. workBuffer _ Array new: 64.! ! !SHA256 methodsFor: 'private' stamp: 'msh 6/17/2003 02:09'! maj ^ ( ( ( ( state at: 1 ) bitAnd: ( state at: 2 ) ) bitXor: ( ( state at: 1 ) bitAnd: ( state at: 3 ) ) ) bitXor: ( ( state at: 2 ) bitAnd: ( state at: 3 ) ) ).! ! !SHA256 methodsFor: 'private' stamp: 'msh 6/17/2003 02:14'! s0: anInteger ^ ((((self rightRotate: anInteger by: 7) bitXor: (self rightRotate: anInteger by: 18)) bitXor: (anInteger >> 3)) bitAnd: 16rFFFFFFFF).! ! !SHA256 methodsFor: 'private' stamp: 'msh 6/17/2003 02:14'! s1: anInteger ^ ((((self rightRotate: anInteger by: 17) bitXor: (self rightRotate: anInteger by: 19)) bitXor: (anInteger >> 10)) bitAnd: 16rFFFFFFFF).! ! !SHA256 methodsFor: 'private' stamp: 'msh 6/17/2003 02:13'! sum0: anInteger ^ ((((self rightRotate: anInteger by: 2) bitXor: (self rightRotate: anInteger by: 13)) bitXor: (self rightRotate: anInteger by: 22)) bitAnd: 16rFFFFFFFF).! ! !SHA256 methodsFor: 'private' stamp: 'msh 6/17/2003 02:13'! sum1: anInteger ^ ((((self rightRotate: anInteger by: 6) bitXor: (self rightRotate: anInteger by: 11)) bitXor: (self rightRotate: anInteger by: 25)) bitAnd: 16rFFFFFFFF).! ! !SHA256 methodsFor: 'private' stamp: 'msh 6/17/2003 02:25'! transform | t1 t2 | self bufferConvert. 1 to: 16 do: [ :i | workBuffer at: i put: ( wordBuffer at: i ). ]. 17 to: 64 do: [ :i | workBuffer at: i put: ( ((self s1:(workBuffer at: (i-2))) + (workBuffer at: (i-7)) + (self s0:(workBuffer at: (i-15))) + (workBuffer at: (i-16))) bitAnd: 16rFFFFFFFF ). ]. 1 to: 8 do: [ :i | savedState at: i put: ( state at: i ). ]. 1 to: 64 do: [ :i | t1 _ ((state at: 8) + (self sum1:(state at: 5)) + (self ch) + (K at: i) + (workBuffer at: i)) bitAnd: 16rFFFFFFFF. t2 _ ((self sum0: (state at: 1)) + (self maj)) bitAnd: 16rFFFFFFFF. state at: 8 put: (state at: 7). state at: 7 put: (state at: 6). state at: 6 put: (state at: 5). state at: 5 put: (((state at: 4) + t1) bitAnd: 16rFFFFFFFF). state at: 4 put: (state at: 3). state at: 3 put: (state at: 2). state at: 2 put: (state at: 1). state at: 1 put: ((t1 + t2) bitAnd: 16rFFFFFFFF). ]. 1 to: 8 do: [ :i | state at: i put: ( ( ( state at: i ) + ( savedState at: i ) ) bitAnd: 16rFFFFFFFF ). ].! ! !SHA256 class methodsFor: 'instance creation' stamp: 'msh 6/17/2003 01:53'! new ^super new initialize.! ! !SHA256 class methodsFor: 'class initialization' stamp: 'msh 6/17/2003 01:55'! initialize K _ #( 16r428A2F98 16r71374491 16rB5C0FBCF 16rE9B5DBA5 16r3956C25B 16r59F111F1 16r923F82A4 16rAB1C5ED5 16rD807AA98 16r12835B01 16r243185BE 16r550C7DC3 16r72BE5D74 16r80DEB1FE 16r9BDC06A7 16rC19BF174 16rE49B69C1 16rEFBE4786 16r0FC19DC6 16r240CA1CC 16r2DE92C6F 16r4A7484AA 16r5CB0A9DC 16r76F988DA 16r983E5152 16rA831C66D 16rB00327C8 16rBF597FC7 16rC6E00BF3 16rD5A79147 16r06CA6351 16r14292967 16r27B70A85 16r2E1B2138 16r4D2C6DFC 16r53380D13 16r650A7354 16r766A0ABB 16r81C2C92E 16r92722C85 16rA2BFE8A1 16rA81A664B 16rC24B8B70 16rC76C51A3 16rD192E819 16rD6990624 16rF40E3585 16r106AA070 16r19A4C116 16r1E376C08 16r2748774C 16r34B0BCB5 16r391C0CB3 16r4ED8AA4A 16r5B9CCA4F 16r682E6FF3 16r748F82EE 16r78A5636F 16r84C87814 16r8CC70208 16r90BEFFFA 16rA4506CEB 16rBEF9A3F7 16rC67178F2 ).! ! !Socket commentStamp: 'crl 2/13/2004 14:00' prior: 0! ' I am an abstract Class. Each instance of my concrete subclasses provides access to an Internet Protocol connection with a network peer. Author: Craig Latta ! !SocketAddress commentStamp: 'crl 2/13/2004 14:01' prior: 0! ' My instances indicate host/port combinations for Sockets. Each instance consists of six bytes: four to indicate a host, and two to indicate a port. Author: Craig Latta ! !SocketAddress methodsFor: 'initialization'! port: anInteger "Use network byte order (most-significant-first)." bytes at: 5 put: (anInteger bitShift: -8); at: 6 put: (anInteger bitAnd: 255)! ! !SocketAddress methodsFor: 'accessing'! port "Use network byte order (most-significant-first)." ^ ((bytes at: 5) bitShift: 8) + (bytes at: 6)! ! !SocketAddressResolver commentStamp: 'crl 2/13/2004 14:01' prior: 0! ' My instances resolve SocketAddresses for Sockets. Author: Craig Latta ! !SocketStream commentStamp: 'crl 2/13/2004 14:06' prior: 0! ' I am an abstract Class. Instances of my concrete subclasses provide a stream-oriented message interface for reading and writing with sockets. Author: Craig Latta ! !Sorcerer commentStamp: 'crl 2/12/2004 23:17' prior: 0! ' Each of my instances waits for an Apprentice in a remote system to connect. When one does, a Sorcerer uses object identities provided the Apprentice to create Others (proxies) for the Apprentice object itself, as well as the system dictionary of the Apprentice's system. Thereafter, the Sorcerer may send messages to any object in the remote system (possibly using convenience behavior provided by the Apprentice). Author: Craig Latta ! !StandardFileStream class methodsFor: 'as yet unclassified' stamp: 'msh 11/7/2005 12:50'! oldFileNamed: fileName | selection | (self isAFileNamed: fileName) ifTrue: [^ self new open: fileName forWrite: true]. selection _ (PopUpMenu labels: 'create a new file choose another name cancel') startUpWithCaption: (FileDirectory localNameFor: fileName) , ' does not exist.'. selection = 1 ifTrue: [^ self new open: fileName forWrite: true]. selection = 2 ifTrue: [^ self oldFileNamed: (FillInTheBlank request: 'Enter a new file name' initialAnswer: (FileDirectory localNameFor: fileName))]. "self halt"! ! !SymmetricStreamCipher methodsFor: 'output size' stamp: 'msh 5/11/2005 14:40'! outputSize: anIndex ^ anIndex .! ! !SymmetricStreamCipher methodsFor: 'encryption' stamp: 'msh 5/11/2005 15:40'! decrypt: cleartext ^ self encrypt: cleartext .! ! !SymmetricStreamCipher methodsFor: 'encryption' stamp: 'msh 5/11/2005 15:40'! decrypt: cleartext into: ciphertext self encrypt: cleartext into: ciphertext .! ! !SymmetricStreamCipher methodsFor: 'encryption' stamp: 'msh 5/11/2005 15:41'! decrypt: cleartext into: ciphertext withOffset: anOffset self encrypt: cleartext into: ciphertext withOffset: anOffset.! ! !SymmetricStreamCipher methodsFor: 'encryption' stamp: 'msh 5/11/2005 15:39'! encrypt: cleartext | rv | rv _ ByteArray new: ( self outputSize: ( cleartext size ) ). self encrypt: cleartext into: rv. ^ rv .! ! !SymmetricStreamCipher methodsFor: 'encryption' stamp: 'msh 5/11/2005 15:38'! encrypt: cleartext into: ciphertext self encrypt: cleartext into: ciphertext withOffset: 0.! ! !SymmetricStreamCipher methodsFor: 'encryption' stamp: 'msh 5/11/2005 15:38'! encrypt: cleartext into: ciphertext withOffset: anOffset | keystream | keystream _ self next: ( cleartext size ) . 1 to: ( keystream size ) do: [ :index | ciphertext at: ( index + anOffset ) put: ( ( cleartext at: index ) bitXor: ( keystream at: index ) ) . ]. 1 to: ( keystream size ) do: [ :index | keystream at: index put: 0. ]! ! !ARC4 commentStamp: '' prior: 0! This class represents an "Alleged RC4" instance. RC4 (tm) is a trademarked symmetric stream cipher from RSA Data Security, Inc. Code for a "RC4 Compatible" cipher was eventually leaked to the internet which is where this implementation comes from. Before using ARC4, you should know that there are a number of terrible attacks against it. Shamir, Mantin, and Flurher documented several weaknesses in the cipher that, in my humble opinion, make it unsafe at any key length. So let's say you want to encrypt something with ARC4. The basic pattern is: initialize with the key, then call the encrypt (or decrypt) functions. ARC4 is a Vernam stream cipher, so we don't have to worry about block size or modes of encryption. Before using any Vernam cipher, however, you should know that it's considered unsafe to encrypt two different messages with the same key. There's more details in Schneier's Applied Crypto or Menezes, et al.'s Handbook of Applied Crypto about this. So, this class takes a key in a byte array, then encrypts plaintext in a byte array to produce a byte array of ciphertext. Here's an example | plaintext ciphertext ncryptor recovered | plaintext _ 'When in the course of human events.' asByteArray. ncryptor _ (ARC4 new). ciphertext _ ncryptor initialize: ('I am a very bad password' asByteArray); encrypt: plaintext. ncryptor clearSensitiveData. ncryptor _ (ARC4 new). recovered _ ncryptor initialize: ('I am a very bad password' asByteArray); encrypt: plaintext. ncryptor clearSensitiveData. At the end of this fragment, plaintext and recovered should both be ByteArray's containing the same data.! !ARC4 methodsFor: 'sensitive data' stamp: 'msh 5/11/2005 14:42'! clearSensitiveData i _ 0. j _ 0. 1 to: 256 do: [ :index | sbox at: index put: 0. ].! ! !ARC4 methodsFor: 'encryption' stamp: 'msh 5/11/2005 15:09'! initialize: aKey | ell jay temp | i _ 0. j _ 0. sbox _ ByteArray new: 256. 1 to: 256 do: [ :index | sbox at: index put: ( index - 1 ). ]. ell _ aKey size. jay _ 0. 0 to: 255 do: [ :index | jay _ ( jay + ( sbox at: ( index + 1 ) ) + ( aKey at: ( ( index \\ ell ) + 1 ) ) ) \\ 256. temp _ sbox at: ( index + 1). sbox at: ( index + 1 ) put: ( sbox at: ( jay + 1 ) ). sbox at: ( jay + 1 ) put: temp. ]. temp _ 0. ell _ 0. jay _ 0. ! ! !ARC4 methodsFor: 'keystream' stamp: 'msh 11/7/2005 15:34'! next | rv temp | i _ ( i + 1 ) \\ 256. j _ ( j + ( sbox at: ( i + 1) ) ) \\ 256. temp _ sbox at: ( i + 1 ). sbox at: ( i + 1 ) put: ( sbox at: ( j + 1 ) ). sbox at: ( j + 1 ) put: temp . rv _ sbox at: ( ( ( sbox at: ( i + 1 ) ) + ( sbox at: ( j + 1 ) ) ) \\ 256 ) + 1. ^ rv .! ! !ARC4 methodsFor: 'keystream' stamp: 'msh 5/11/2005 15:20'! next: aCount | rv | rv _ ByteArray new: aCount. self next: aCount into: rv. ^ rv .! ! !ARC4 methodsFor: 'keystream' stamp: 'msh 5/11/2005 15:12'! next: aCount into: anArray 1 to: aCount do: [ :count | anArray at: count put: ( self next ). ].! ! !TCPSocket commentStamp: 'crl 2/13/2004 14:02' prior: 0! ' My instances are conduits of information between the local host and network peers, using the Transmission Control Protocol (TCP). Author: Craig Latta ! !ClientTCPSocket commentStamp: 'crl 2/13/2004 12:21' prior: 0! ' I am an abstract Class. Instances of my concrete subclasses are TCP sockets used for communicating to or from clients in a client/server relationship. Author: Craig Latta ! !IncomingClientTCPSocket commentStamp: 'crl 2/13/2004 12:29' prior: 0! My instances are TCP sockets used by servers for communicating to clients in a client/server relationship. Author: Craig Latta ! !OutgoingClientTCPSocket commentStamp: 'crl 2/13/2004 12:30' prior: 0! ' My instances are TCP sockets used for communicating from clients to servers in a client/server relationship. Author: Craig Latta ! !ServerTCPSocket commentStamp: 'crl 2/13/2004 13:53' prior: 0! My instances are TCP sockets used for accepting clients in client/server relationships. Author: Craig Latta ! !TCPStream commentStamp: 'crl 2/13/2004 14:07' prior: 0! ' My instances provide a stream-oriented message interface for reading and writing TCP sockets. Author: Craig Latta ! !URI commentStamp: 'crl 2/13/2004 14:15' prior: 0! ' I am an abstract class. Instances of my concrete subclasses identify network resources, as specified in RFC 2396. All my instance variables are decoded and ready for an application to use. If escape sequences appeared in the original URI, octets which are not acceptable as literals in that particular URI component may be present. Use >>printOn: to get the representation required by RFC 2396, in which these octets are escaped using $%. I do not implement the following portions of RFC 2396: - Appendix E (Recommendations for Delimiting URI in Context) - Appendix F (Abbreviated URLs) Where the BNF and the examples in RFC 2396 do not agree, I comply with the examples. Where RFC 2396 conflicts with other RFCs, I comply with the more authoritative RFC for that topic. All known cases of conflict are documented in the relevant code and tests. The classes in the framework follow (existing classes used for instance variables or superclasses are elided). URI HierarchicalURI (has an Authority and a PathSegmentCollection) OpaqueURI Authority (determines the path namespace) HostAuthority (has a HostIdentifier) RegisteredAuthority HostIdentifier (identifies a network-accessible host) DomainName IPv4Address URIStream (understands encoding and decoding of URI characters) IllegalURIException (indicates a URI-related error) URITest (tests the classes in this framework) instance variables: - scheme a String containing the scheme of a URI - fragment a String containing the fragment of a URI Author: asparagi! !HierarchicalURI commentStamp: 'crl 2/13/2004 14:13' prior: 0! ' My instances represent hierarchical URIs, as specified in RFC 2396. instance variables: - authority the Authority component of a URI - path a PathSegmentCollection representing the path of a URI - query a String containing the query of a URI Author: asparagi! !OpaqueURI commentStamp: 'crl 2/13/2004 14:14' prior: 0! ' My instances represent opaque URIs, as specified in RFC 2396. instance variable: - opaquePart a String containing the opaque part of a URI Author: asparagi ! !URIStream commentStamp: 'crl 2/13/2004 14:15' prior: 0! ' My instances are streams that know how to encode and decode the characters that might appear in a URI, as specified in RFC 2396. instance variables: - stream a Stream used to answer messages, sometimes a pointer to self class variables: - URICharacters a Dictionary mapping Strings describing URI character classes to IdentitySets of those characters Author: asparagi! !URITest commentStamp: 'crl 2/13/2004 14:15' prior: 0! ' I test class URI and related classes for RFC 2396 compliance. My automatically generated tests came, with very little modification, from Michael Rueger's TestURI class; thanks, Michael!! Author: asparagi! !UUID commentStamp: 'crl 2/12/2004 22:27' prior: 0! ' Each of my instances is a universally-unique identifier, as proscribed by the Leach/Salz algorithm. Author: Craig Latta ! !UUIDGenerator commentStamp: 'crl 2/12/2004 22:31' prior: 0! ' Each of my instances generates the bits for a UUID, as proscribed by the Leach/Salz algorithm. Only version four of the algorithm is supported as Smalltalk code here, although the host platform might be able to provide support the other three, accessible by an virtual machine extension. Author: Craig Latta ! !UndeclaredLiteralMarker commentStamp: 'crl 2/12/2004 22:22' prior: 0! ' Each of my instances indicates, to a remote system reading a serialized CompiledMethod, a method literal which refers to an association in the Undeclared dictionary. Author: Craig Latta ! !Uninstalled commentStamp: 'crl 2/12/2004 22:14' prior: 0! ' I am an abstract Class. Each of my subclasses serves only as a placeholder for the missing superclass of some class defined via module synchronization with a remote system. Author: Craig Latta ! !IllegalURIException commentStamp: 'crl 2/13/2004 14:14' prior: 0! ' My instances are raised when a URI is requested, but cannot be parsed from a String or Stream. The tag instance variable should be the half-formed URI object which was being constructed when the error occurred. Author: asparagi ! EncryptedStream class removeSelector: #with:! EncryptedStream class removeSelector: #new! MessageDigest initialize! MD2 initialize! MD5 initialize! Password class removeSelector: #fileInPasswordsFromStream:withPassword:! Password class removeSelector: #password! Preferences initialize! SHA1 initialize! SHA256 initialize! Smalltalk removeClassNamed: #ModuleInstallationServer! Smalltalk removeClassNamed: #Foo! Smalltalk removeClassNamed: #ModuleRequestServer!