All pastes #442941 Raw Edit

Someone

public text v1 · immutable
·published 2007-04-16 15:53 UTC
rendered paste body
----SNAPSHOT----an Array(16 April 2007 12:54:25 pm) squeak-stuff.image priorSource: 7569629!

'From Squeak3.7beta of ''1 April 2004'' [latest update: #5878] on 13 April 2004 at 5:16:31 pm'!

"Change Set:		Crypto
Date:			23 November 2002
Author:			Luciano Notarfrancesco, Carlos Sarraute

The cryptography package provides some basic cryptographic algorithms and protocols. This change set integrates algorithms implemented by several members of the Squeak community, including Leandro Caniglia, Duane Maxwell, John Maloney, Luciano Notarfrancesco, Carlos Sarraute and Robert Withers. For examples of use, browse the tests (CryptoTest)."!

Object subclass: #ARC4
	instanceVariableNames: 'sbox i j'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-RC4'!

TestCase subclass: #ASN1TestCase
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-ASN1'!

Object subclass: #ASN1Value
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: 'ASN1Constants'
	category: 'Cryptography-ASN1'!

ASN1Value subclass: #ASN1BitString
	instanceVariableNames: 'bytes'
	classVariableNames: ''
	poolDictionaries: 'ASN1Constants'
	category: 'Cryptography-ASN1'!

ASN1Value subclass: #ASN1ObjectId
	instanceVariableNames: 'oid description'
	classVariableNames: ''
	poolDictionaries: 'ASN1Constants'
	category: 'Cryptography-ASN1'!

Object subclass: #BlockCipher
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography'!

BlockCipher subclass: #BlockCipherMode
	instanceVariableNames: 'cipher vector'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography'!

BlockCipherMode subclass: #CBC
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography'!

BlockCipherMode subclass: #CFB
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography'!

TestCase subclass: #CryptoTest
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-Tests'!

BlockCipher subclass: #DES
	instanceVariableNames: 'cookedKey key encrypting'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-DES'!
!DES commentStamp: '<historical>' prior: 0!
This class implements the Data Encryption Standard (DES) block cipher per
ANSI X3.92.  It requires the presence of the 'DESPlugin'.  At some future
date the functionality of the plugin may be provided in pure Smalltalk, but
the slowness would be prohibitive for anything other than trivial usage.
The main barrier to translation is the heavy use of zero-based indexing of
arrays.

How to use: you first provide an 8-byte key which will be used to encode
and decode the data. Internally, this is 'cooked' into a 32-word format to
speed up the encryption process.  The data is then sent in 8-byte packets
to be encoded or decoded.  You must externally account for padding.  See
the 'testing' category on the class side for examples.

As of this date (1/26/2000), the U.S. Government has lifted many of the
previous restrictions on the export of encryption software, but you should
check before exporting anything including this code.

Submitted by Duane Maxwell.

!

ProtoObject subclass: #DESPlugin
	instanceVariableNames: 'byteBit bigByte pc1 pc2 totRot sp1 sp2 sp3 sp4 sp5 sp6 sp7 sp8'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-DES'!
!DESPlugin commentStamp: '<historical>' prior: 0!
This plugin implements the Data Encryption Standard (DES).

You should build this plugin with the module name 'DESPrims'.

See class comments for 'DES' for usage.

Submitted by Duane Maxwell
!

Object subclass: #DSAKeyPairGenerator
	instanceVariableNames: 'p q g x y random'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-DSA'!

ProtoObject subclass: #DSAPlugin
	instanceVariableNames: 'dsaRemainder dsaDivisor dsaQuotient remainderDigitCount divisorDigitCount'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-DSA'!
!DSAPlugin commentStamp: '<historical>' prior: 0!
This plugin defines primitives that support the DigitalSignatureAlgorithm class. Three of these primitives support fast multiplication and division of very large integers, three others support the SecureHashAlgorithm.
!

Object subclass: #DSAPrivateKey
	instanceVariableNames: 'p q g x'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-DSA'!

Object subclass: #DSAPublicKey
	instanceVariableNames: 'p q g y'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-DSA'!

Object subclass: #DiffieHellman
	instanceVariableNames: 'prime generator secret sharedKey'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-ElGamal'!
!DiffieHellman commentStamp: 'cs 12/5/2002 18:50' prior: 0!
I represent the basic version of the Diffie-Hellman key agreement. 
See Handbook of Applied Cryptography, Ch. 12, p. 516

One time setup:
* a safe prime p and a generator alpha of Zp* are published.

Protocol actions:
* Alice chooses a random secret x between 1 and p-2.
* Alice sends Bob message alpha^x mod p.
* Bob chooses a random secret y between 1 and p-2.
* Bob sends Alice message alpha^y mod p.
* Alice receives alpha^y and computes the shared key:
	K = (alpha^y)^x mod p.
* Bob receives alpha^x and computes the shared key:
	K = (alpha^x)^y mod p.

Example from testCase:
| alice bob fromAlice fromBob k1 k2 |
alice _ DiffieHellman bits: 15.
bob _ DiffieHellman prime: alice prime generator: alice generator.
fromAlice _ alice sendMessage.
fromBob _ bob sendMessage.
k1 _ alice receiveMessage: fromBob.
k2 _ bob receiveMessage: fromAlice.
self assert: k1 = k2
!

Object subclass: #ElGamalKeyGenerator
	instanceVariableNames: 'p alpha a'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-ElGamal'!
!ElGamalKeyGenerator commentStamp: '<historical>' prior: 0!
The ElGamal public-key encryption scheme is related to the Diffie-Hellman key agreement. Their security is based on the intractability of the same number theoretic problems (the discrete logarithm problem and the Diffie-Hellman problem).

See Handbook of Applied Cryptography, Ch. 8, p. 294.

Key generation:
* Generate a large random prime p and a generator alpha of the multiplicative group Zp* of the integers modulo p
* Select a random integer a between 1 and p-2, and compute alpha^a mod p
* The public key is (p, alpha, alpha^a)
  The private key is a

Example of encryption:
| elgamal pub priv c |
elgamal _ ElGamalKeyGenerator new.
elgamal generateKeysOfSize: 15.
pub _ elgamal publicKey.
priv _ elgamal privateKey.
c _ pub encryptElement: 31.
priv decryptElement: c.


Example of signature:
| elgamal pub priv signature |
elgamal _ ElGamalKeyGenerator new.
elgamal generateKeysOfSize: 15.
pub _ elgamal publicKey.
priv _ elgamal privateKey.
signature _ priv signMessage: 'hello'.
pub verifySignature: signature onMessage: 'hello'.

!

Object subclass: #ElGamalPrivateKey
	instanceVariableNames: 'modulo generator secretExponent'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-ElGamal'!
!ElGamalPrivateKey commentStamp: '<historical>' prior: 0!
See Handbook of Applied Cryptography, Ch. 8, p. 295.

Here we use the notation:
	p = modulo
	alpha = generator
	a = secretExponent

Decryption:
* Receive the ciphertext c = (gamma, delta).
* Use the private key to compute:
	gamma^(p-1-a) = gamma^(-a) = alpha^(-a*k) mod p
* Recover m = (gamma^(p-1-a)) * delta mod p

Signature generation:
* Select a random secret integer k between 1 and p-2, with gcd(k, p-1) = 1.
* Compute r = alpha^k mod p.
* Compute k^(-1) mod (p-1).
* Compute s = k^(-1) * ( h(m) - a*r ) mod (p-1), where h is a hash function.
* The signature for m is the pair (r,s).


!

Object subclass: #ElGamalPublicKey
	instanceVariableNames: 'modulo generator generatorRaisedToA'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-ElGamal'!
!ElGamalPublicKey commentStamp: '<historical>' prior: 0!
See Handbook of Applied Cryptography, Ch. 8, p. 295.

Here we use the notation:
	p = modulo
	alpha = generator
	alpha^a = generatorRaisedToA

Encryption:
* Obtain A's public key (p, alpha, alpha^a).
* Represent the message as an integer m between 0 and p-1.
* Select a random integer k between 1 and p-2.
* Compute:
		gamma = alpha^k mod p
		delta = m * (alpha^a)^k mod p.
* Send the ciphertext c = (gamma, delta).

Signature verification:
* Obtain A's public key (p, alpha, alpha^a).
* Verify that r is between 1 and p-1, if not then reject the signature.
* Compute v1 = (alpha^a)^r * r^s mod p.
* Compute h(m) where h is a hash function
* Compute v2 = alpha^h(m) mod p.
* Accept the signature if and only if v1=v2.

!

Object subclass: #HMAC
	instanceVariableNames: 'hash key ipad epad'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography'!
!HMAC commentStamp: '<historical>' prior: 0!
HMAC is a mechanism for message authentication using cryptographic hash functions. HMAC can be used with any iterative cryptographic hash function, e.g., MD5, SHA-1, in combination with a secret shared key.  The cryptographic strength of HMAC depends on the properties of the underlying hash function.

See RFC 2114.!

Object subclass: #HashFunction
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography'!

HashFunction subclass: #MD4
	instanceVariableNames: 'a b c d input output'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-MD4'!

HashFunction subclass: #MD5
	instanceVariableNames: 'state'
	classVariableNames: 'ABCDTable IndexTable ShiftTable SinTable'
	poolDictionaries: ''
	category: 'Cryptography-MD5'!
!MD5 commentStamp: '<historical>' prior: 0!
This class implements the MD5 128-bit one-way hash function.  It relies on
the ThirtyTwoBitRegister class supplied as part of the "Digital Signatures"
functionality included in Squeak 2.7.  As of this date (1/20/2000), the
U.S. Government has lifted many of the previous restrictions on the export
of encryption software, but you should check before exporting anything
including this code.  MD5 is commonly used for some secure Internet
protocols, including authentication in HTTP, which is why I wrote it.

Submitted by Duane Maxwell

!

Object subclass: #MillerRabin
	instanceVariableNames: 'target iterations satisfied samples minusOne k n0'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-Support'!
!MillerRabin commentStamp: '<historical>' prior: 0!
My instances are Miller-Rabin algorithms. Miller-Rabin is a probabilistic algorithm for primality testing.!

BlockCipherMode subclass: #OFB
	instanceVariableNames: 'vectorStream'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography'!

Object subclass: #PrimesFinder
	instanceVariableNames: 'wheel candidate'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-Support'!
!PrimesFinder commentStamp: '<historical>' prior: 0!
My instances search for primes of a given size. They implement a probabilistic method. For speed, they first test for divisibility by the primest up to 2000 (in a deterministic way). Next, they employ a probabilistic test (such as MillerRabin).!

Object subclass: #PrimesWheel
	instanceVariableNames: 'primes residues satisfied'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-Support'!
!PrimesWheel commentStamp: '<historical>' prior: 0!
My instances are wheels of primes. See the class comment in PrimesFinder.!

Object subclass: #RSAEncryptionScheme
	instanceVariableNames: 'hash hashLen rand publicKey privateKey encodingParameter'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-RSA'!
!RSAEncryptionScheme commentStamp: 'rww 4/11/2004 14:55' prior: 0!
Example:

| rsa pub priv rsaes c |
rsa _ RSAKeyPairGenerator new.
rsa bits: 1024.
pub _ rsa publicKey.
priv _ rsa privateKey. 

rsaes _ RSAEncryptionScheme new.
rsaes setPublicKey: pub privateKey: priv parameter: 'p'.

c _ rsaes encrypt: 'hola'.
(rsaes decrypt: c) asString.

!

Object subclass: #RSAKey
	instanceVariableNames: 'exponent modulo'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-RSA'!
!RSAKey commentStamp: '<historical>' prior: 0!
My instances are RSA algorithms.!

Object subclass: #RSAKeyPairGenerator
	instanceVariableNames: 'bits p q d'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-RSA'!
!RSAKeyPairGenerator commentStamp: '<historical>' prior: 0!
My instances generate public/private RSA pairs.!

Stream subclass: #RandomPool
	instanceVariableNames: 'key pool outputStream inputIndex'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-Support'!

RandomPool class
	instanceVariableNames: 'default'!

BlockCipher subclass: #Rijndael
	instanceVariableNames: 'nB nK nR shiftOffset1 shiftOffset2 shiftOffset3 expandedKey eqExpandedKey state'
	classVariableNames: 'InvT0 InvT1 InvT2 InvT3 LogInverseTable LogTable RoundConstant SubByte SubByteInverse T0 T1 T2 T3'
	poolDictionaries: ''
	category: 'Cryptography-Rijndael'!

HashFunction subclass: #SHA1
	instanceVariableNames: 'totalA totalB totalC totalD totalE totals'
	classVariableNames: 'K1 K2 K3 K4'
	poolDictionaries: ''
	category: 'Cryptography-SHA1'!
!SHA1 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.
!

Stream subclass: #SecureRandom
	instanceVariableNames: 'seed key'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-Support'!
!ThirtyTwoBitRegister commentStamp: '<historical>' prior: 32633487!
I represent a 32-bit register. An instance of me can hold any non-negative integer in the range [0..(2^32 - 1)]. Operations are performed on my contents in place, like a hardware register, and results are always modulo 2^32.

This class was primarily meant for use by the SHA1 class.
!

BlockCipher subclass: #TripleDES
	instanceVariableNames: 'des1 des2 des3'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Cryptography-DES'!
!ARC4 methodsFor: 'accessing' stamp: 'len 8/6/2002 20:20'!
decrypt: aByteArray
	^ self encrypt: aByteArray! !
!ARC4 methodsFor: 'accessing' stamp: 'len 8/6/2002 20:20'!
encrypt: aByteArray
	1 to: aByteArray size do: [ :each | aByteArray at: each put: ((aByteArray at: each) bitXor: self next)]! !
!ARC4 methodsFor: 'accessing' stamp: 'len 8/6/2002 20:08'!
key: aByteArray
	| k other |
	sbox _ (0 to: 255) asByteArray.
	k _ (0 to: 255) collect: [ :each | aByteArray at: each \\ aByteArray size + 1].
	other _ 0.
	1 to: 256 do: [ :each |
		other _ other + (sbox at: each) + (k at: each) \\ 256.
		sbox swap: each with: other+1].
	i _ j _ 0! !
!ARC4 methodsFor: 'accessing' stamp: 'len 8/6/2002 20:15'!
next
	| t |
	i _ i + 1 \\ 256.
	j _ j + (sbox at: i+1) \\ 256.
	sbox swap: i+1 with: j+1.
	t _ (sbox at: i+1) + (sbox at: j+1) \\ 256.
	^ sbox at: t+1! !
!ASN1TestCase methodsFor: 'Running' stamp: 'rww 1/1/2003 12:08'!
pvtTestInteger: anInteger

	self  assert: (ASN1Value fromAsnDer: anInteger encodeAsnDer readStream) = anInteger.
! !
!ASN1TestCase methodsFor: 'Running' stamp: 'rww 1/1/2003 14:45'!
pvtTestOidString: string

	| oid |
	oid := ASN1ObjectId fromString: string.
	self assert: (ASN1Value fromAsnDer: oid encodeAsnDer readStream) = oid.
	self assert: oid printString = string.! !
!ASN1TestCase methodsFor: 'Running' stamp: 'rww 1/1/2003 12:41'!
pvtTestSequence: aSequence

	| collection |
	collection := aSequence asOrderedCollection.
	self  assert: (ASN1Value fromAsnDer: collection encodeAsnDer readStream) = collection.

! !
!ASN1TestCase methodsFor: 'Running' stamp: 'rww 1/2/2003 01:16'!
testBitString

	| bits |
	bits := ASN1BitString fromByteArray: 2r011011100101110111 asByteArray.
	self assert: (ASN1Value fromAsnDer: bits encodeAsnDer readStream) = bits.
	bits := ASN1BitString fromByteArray: 123456789 encodeAsnDer.
	self assert: (ASN1Value fromAsnDer: bits encodeAsnDer readStream) = bits.
! !
!ASN1TestCase methodsFor: 'Running' stamp: 'rww 12/8/2002 08:29'!
testInteger

	| maxInt |
	maxInt := (2 raisedTo: 31) - 1.		"max for signed integer"
	self
		pvtTestInteger: 42;
		pvtTestInteger: 155687;
		pvtTestInteger: -42;
		pvtTestInteger: -155687;
		pvtTestInteger: maxInt;
		pvtTestInteger: maxInt negated.
	self pvtTestInteger: 9872761208756012378465108243650872346508731560437652374653276528347658734265071340514523487650238745602873456237411108734617760184650837246012876374650274365027834503784520345320543026147650137480651746501735173265134765.
! !
!ASN1TestCase methodsFor: 'Running' stamp: 'rww 1/1/2003 12:46'!
testNull

	self assert: (ASN1Value fromAsnDer: nil encodeAsnDer readStream) = nil.
! !
!ASN1TestCase methodsFor: 'Running' stamp: 'rww 1/2/2003 00:36'!
testOid
	"SnmpTestCase debug: #testOid"

	| string |
	string := '1.3.6.1.2.1.1.1.0'.
	self pvtTestOidString: string.
	string := '1.3.6.108765.2.1.1.1.0'.
	self pvtTestOidString: string.
! !
!ASN1TestCase methodsFor: 'Running' stamp: 'rww 1/1/2003 11:59'!
testSequence

	self
		pvtTestSequence: #(42 213)! !
!ASN1Value methodsFor: 'private - parsing' stamp: 'rww 1/1/2003 14:50'!
encodeAsnDer

	| aStream |
	aStream := WriteStream on: (ByteArray new: 16).
	self encodeAsnDerOn: aStream.
	^aStream contents! !
!ASN1BitString methodsFor: 'accessing' stamp: 'rww 1/2/2003 01:12'!
bytes
	"Answer the receiver's instance variable bytes."

	^bytes! !
!ASN1BitString methodsFor: 'accessing' stamp: 'rww 1/2/2003 01:12'!
bytes: anObject
	"Set the receiver's instance variable bytes to anObject."

	bytes := anObject! !
!ASN1BitString methodsFor: 'private - parsing' stamp: 'rww 1/2/2003 01:13'!
= anotherBitString

	^ self bytes = anotherBitString bytes! !
!ASN1BitString methodsFor: 'private - parsing' stamp: 'rww 1/2/2003 01:15'!
encodeAsnDerOn: aStream
	aStream nextPut: 3.
	(self bytes size + 1) encodeAsnDerLengthOn: aStream.
	aStream 
		nextPut: 0;
		nextPutAll: self bytes asByteArray.
	^aStream
! !
!ASN1BitString methodsFor: 'private - parsing' stamp: 'rww 1/2/2003 01:13'!
printOn: aStream

	aStream nextPutAll: self bytes asString! !
!ASN1ObjectId methodsFor: 'accessing' stamp: 'rww 12/8/2002 10:07'!
description
	"Answer the receiver's instance variable description."

	^description! !
!ASN1ObjectId methodsFor: 'accessing' stamp: 'rww 12/8/2002 10:07'!
description: anObject
	"Set the receiver's instance variable description to anObject."

	description := anObject! !
!ASN1ObjectId methodsFor: 'accessing' stamp: 'rww 12/8/2002 10:07'!
oid
	"Answer the receiver's instance variable oid."

	^oid! !
!ASN1ObjectId methodsFor: 'accessing' stamp: 'rww 12/8/2002 10:07'!
oid: anObject
	"Set the receiver's instance variable oid to anObject."

	oid := anObject! !
!ASN1ObjectId methodsFor: 'private - parsing' stamp: 'rww 1/1/2003 14:45'!
= anotherOid

	^ self oid = anotherOid oid! !
!ASN1ObjectId methodsFor: 'private - parsing' stamp: 'rww 1/2/2003 00:47'!
encodeAsnDerOn: aStream

	| dataStream oidTokens b n lengthStream bytes data |
	aStream nextPut: 6.
	dataStream := WriteStream on: (ByteArray new: 16).
	oidTokens := self oid tokensBasedOn: $..
	dataStream nextPut: (((oidTokens at: 1) asInteger * 40) bitOr: (oidTokens at: 2) asInteger).
	3 to: oidTokens size do: [:i | 
		b := (oidTokens at: i) asInteger.
		(b <= 16r7F)
			ifTrue: [dataStream nextPut: b]
			ifFalse: [
				n := b.
				lengthStream := WriteStream on: (ByteArray new: 4).
				lengthStream nextPut: (n \\ 128).
				[n := n bitShift: -7.
				(n bitShift: -7) = 0] 
					whileFalse: [lengthStream nextPut: ((n \\ 128) bitOr: 16r80)].
				lengthStream nextPut: ((n \\ 128) bitOr: 16r80).
				bytes := lengthStream contents reversed.
				dataStream 
					nextPutAll: bytes ]].
	data := dataStream contents.
	data size encodeAsnDerLengthOn: aStream.
	aStream nextPutAll: data.
	^aStream
! !
!ASN1ObjectId methodsFor: 'private - parsing' stamp: 'rww 1/1/2003 15:09'!
initializeDescription


"	oid := 'x', self getOID.
	ix := 1.
	[ix < oid size]
		whileTrue: [
			((oid at: ix) = $.)
				ifTrue: [oid at: ix put: $x].
			ix := ix + 1.
		].
	(ASN1ObjectIdentifiers includesKey: oid asSymbol)
		ifTrue: [^ASN1ObjectIdentifiers at: oid asSymbol]
		ifFalse: [^self getOID]"! !
!ASN1ObjectId methodsFor: 'private - parsing' stamp: 'rww 1/1/2003 14:38'!
printOn: aStream

	aStream nextPutAll: self oid! !
!ASN1Value class methodsFor: 'instance creation' stamp: 'rww 1/1/2003 12:02'!
fromAsnDer: stream

	| tag |
	tag := self decodeTagFrom: stream peek.
	^ (self typeClassForTag: tag)
		fromAsnDer: stream
! !
!ASN1Value class methodsFor: 'instance creation' stamp: 'rww 1/1/2003 12:44'!
typeClassForTag: tag

	| types |
	types := Dictionary new
		at: 2 put: Integer;
		at: 3 put: ASN1BitString;
		at: 5 put: nil;
		at: 6 put: ASN1ObjectId;
		at: 16 put: OrderedCollection;
		yourself.
	^ types at: tag ifAbsent: [nil].! !
!ASN1Value class methodsFor: 'asn' stamp: 'rww 1/1/2003 14:58'!
decodeTagFrom: byte

	^ byte bitAnd: 31.

"decodeHighTagNumber: array startingAt: pos

	| i h b |
	tag := 0.
	i := pos.
	h := true.
	[ h ] whileTrue: [
		b := array at: i.
		i := i + 1.
		(b bitAnd: 16r80) = 16r80
			ifFalse: [tag := (tag bitShift: 7) + b. h := false]
			ifTrue: [tag := ((tag bitShift: 7) + (b bitAnd: 16r7F))]
	].
	^i - pos"! !
!ASN1BitString class methodsFor: 'asn' stamp: 'rww 1/2/2003 01:17'!
fromAsnDer: stream

	| length pad bytes |
	stream skip: 1.
	length := Integer asnDerLengthFrom: stream.
	pad := stream next.
	bytes := stream next: length - 1.
	^ self fromByteArray: (bytes copyFrom: 1 to: bytes size - pad).! !
!ASN1BitString class methodsFor: 'asn' stamp: 'rww 1/2/2003 01:16'!
fromByteArray: bytes

	^ ASN1BitString new
		bytes: bytes;
		yourself! !
!ASN1ObjectId class methodsFor: 'asn' stamp: 'rww 1/1/2003 13:23'!
fromAsnDer: stream

	| length b oid len |

	stream skip: 1.
	length := Integer asnDerLengthFrom: stream.
	b := stream next.
	oid := ((b // 40) asString) , '.'  ,((b rem:40) asString).
	len := 0.
	2 to: length do: [:i | 
		b := stream next.
		((b bitAnd: 16r80) = 16r80) 
			ifTrue: [len := ((len bitShift: 7) + (b bitAnd: 16r7F))]
			ifFalse: [
				len := (len bitShift: 7) + b.
				oid := oid , '.', (len asString).
				len := 0]].
	^ self fromString: oid.! !
!ASN1ObjectId class methodsFor: 'asn' stamp: 'rww 1/1/2003 13:22'!
fromString: oidString

	^ self new
		oid: oidString;
		initializeDescription;
		yourself! !
!BlockCipher methodsFor: 'accessing' stamp: 'len 8/9/2002 13:05'!
blockSize
	^ self class blockSize! !
!BlockCipher methodsFor: 'accessing' stamp: 'len 8/2/2002 03:13'!
decryptBlock: cipherText
	^ self subclassResponsibility! !
!BlockCipher methodsFor: 'accessing' stamp: 'len 8/2/2002 03:13'!
encryptBlock: plainText
	^ self subclassResponsibility! !
!BlockCipher methodsFor: 'accessing' stamp: 'len 8/2/2002 02:41'!
key: aKey
	^ self subclassResponsibility! !
!BlockCipher methodsFor: 'accessing' stamp: 'len 8/9/2002 13:05'!
keySize
	^ self class keySize! !
!BlockCipher methodsFor: 'modes' stamp: 'len 8/3/2002 01:47'!
cbc
	^ CBC on: self! !
!BlockCipher methodsFor: 'modes' stamp: 'len 8/3/2002 01:47'!
cfb
	^ CFB on: self! !
!BlockCipher methodsFor: 'modes' stamp: 'len 8/3/2002 01:51'!
ecb
	^ self! !
!BlockCipher methodsFor: 'modes' stamp: 'len 8/3/2002 01:48'!
ofb
	^ OFB on: self! !
!BlockCipher class methodsFor: 'accessing' stamp: 'len 8/9/2002 13:06'!
blockSize
	^ self subclassResponsibility! !
!BlockCipher class methodsFor: 'accessing' stamp: 'len 8/9/2002 13:06'!
keySize
	^ self subclassResponsibility! !
!BlockCipher class methodsFor: 'instance creation' stamp: 'len 8/9/2002 13:15'!
key: aByteArray
	^ self new key: aByteArray! !
!BlockCipherMode methodsFor: 'initialization' stamp: 'len 8/3/2002 01:40'!
setCipher: aCipher
	cipher _ aCipher.
	vector _ ByteArray new: self blockSize! !
!BlockCipherMode methodsFor: 'accessing' stamp: 'len 8/3/2002 01:39'!
blockSize
	^ cipher blockSize! !
!BlockCipherMode methodsFor: 'accessing' stamp: 'len 8/7/2002 16:28'!
initialVector: aByteArray
	vector _ aByteArray! !
!BlockCipherMode methodsFor: 'accessing' stamp: 'len 8/3/2002 01:39'!
key: aByteArray
	cipher key: aByteArray! !
!BlockCipherMode methodsFor: 'accessing' stamp: 'len 8/3/2002 01:39'!
keySize
	^ cipher keySize! !
!BlockCipherMode methodsFor: 'printing' stamp: 'rww 11/19/2002 02:17'!
printOn: aStream
	aStream print: cipher; nextPut: $-; nextPutAll: self class name! !
!BlockCipherMode class methodsFor: 'instance creation' stamp: 'len 8/3/2002 01:48'!
on: aCipher
	^ self new setCipher: aCipher! !
!BlockCipherMode class methodsFor: 'accessing' stamp: 'len 8/9/2002 13:12'!
blockSize
	^ self shouldNotImplement! !
!BlockCipherMode class methodsFor: 'accessing' stamp: 'len 8/9/2002 13:12'!
keySize
	^ self shouldNotImplement! !
!CBC methodsFor: 'accessing' stamp: 'len 8/3/2002 01:43'!
decryptBlock: aByteArray
	vector _ aByteArray copy.
	cipher decryptBlock: aByteArray.
	1 to: aByteArray size do: [ :i | aByteArray at: i put: ((vector at: i) bitXor: (aByteArray at: i))]! !
!CBC methodsFor: 'accessing' stamp: 'len 11/20/2002 11:21'!
encryptBlock: aByteArray
	1 to: aByteArray size do: [ :i | aByteArray at: i put: ((vector at: i) bitXor: (aByteArray at: i))].
	cipher encryptBlock: aByteArray.
	vector _ aByteArray copy! !
!CFB methodsFor: 'accessing' stamp: 'len 8/3/2002 01:44'!
decryptBlock: aByteArray
	vector _ aByteArray copy.
	1 to: aByteArray size do: [ :i | aByteArray at: i put: ((vector at: i) bitXor: (aByteArray at: i))].
	cipher decryptBlock: vector! !
!CFB methodsFor: 'accessing' stamp: 'len 8/3/2002 01:44'!
encryptBlock: aByteArray
	cipher encryptBlock: vector.
	1 to: aByteArray size do: [ :i | aByteArray at: i put: ((vector at: i) bitXor: (aByteArray at: i))].
	vector _ aByteArray copy! !
!CryptoTest methodsFor: 'hash algorithms' stamp: 'len 8/15/2002 01:50'!
testHMAC
	self assert: (MD5 new hmac key: (ByteArray new: 16 withAll: 16r0B); digestMessage: 'Hi There' asByteArray) asInteger = 16r9294727A3638BB1C13F48EF8158BFC9D.
	self assert: (MD5 new hmac key: 'Jefe' asByteArray; digestMessage: 'what do ya want for nothing?' asByteArray) asInteger = 16r750C783E6AB0B503EAA86E310A5DB738.
	self assert: (MD5 new hmac key: (ByteArray new: 16 withAll: 16rAA); digestMessage: (ByteArray new: 50 withAll: 16rDD)) asInteger = 16r56BE34521D144C88DBB8C733F0E8B3F6! !
!CryptoTest methodsFor: 'hash algorithms' stamp: 'len 10/16/2002 16:41'!
testHMACSHA1
	self assert: (SHA1 new hmac key: (ByteArray new: 16 withAll: 16r0B); digestMessage: 'Hi There' asByteArray) = #(16rBC 16rF6 16r85 16r57 16r4C 16rB8 16rAA 16rB1 16rB6 16r42 16rCE 16rCB 16rF3 16r89 16rA0 16r79 16rF6 16r48 16r84 16rF3) asByteArray! !
!CryptoTest methodsFor: 'hash algorithms' stamp: 'len 10/15/2002 19:51'!
testLargeSHA1
	"Here is the third example from the specification document (FIPS PUB 180-1). This example may take several minutes."
	self assert: (SHA1 hashMessage: (String new: 1000000 withAll: $a)) reversed asInteger = 16r34AA973CD4C4DAA4F61EEB2BDBAD27316534016F! !
!CryptoTest methodsFor: 'hash algorithms' stamp: 'len 10/16/2002 16:29'!
testMD4
	self assert: (MD4 hashMessage: #(115 0 115 0 110 0) asByteArray) = #(252 63 129 51 180 217 221 240 64 37 167 140 183 214 26 126) asByteArray! !
!CryptoTest methodsFor: 'hash algorithms' stamp: 'len 8/7/2002 17:46'!
testMD5
	self assert: (MD5 hashMessage: 'a') asInteger = 16r0CC175B9C0F1B6A831C399E269772661.
	self assert: (MD5 hashMessage: 'abc') asInteger = 16r900150983CD24FB0D6963F7D28E17F72.
	self assert: (MD5 hashMessage: 'message digest') asInteger = 16rF96B697D7CB7938D525A2F31AAF161D0.
	self assert: (MD5 hashMessage: 'abcdefghijklmnopqrstuvwxyz') asInteger = 16rC3FCD3D76192E4007DFB496CCA67E13B.
	self assert: (MD5 hashMessage: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') asInteger = 16rD174AB98D277D9F5A5611C2C9F419D9F.
	self assert: (MD5 hashMessage: '12345678901234567890123456789012345678901234567890123456789012345678901234567890') asInteger = 16r57EDF4A22BE3C955AC49DA2E2107B67A! !
!CryptoTest methodsFor: 'hash algorithms' stamp: 'len 10/15/2002 19:51'!
testSHA1
	self assert: (SHA1 hashMessage: 'abc') reversed asInteger = 16rA9993E364706816ABA3E25717850C26C9CD0D89D.
	self assert: (SHA1 hashMessage: 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq') reversed asInteger = 16r84983E441C3BD26EBAAE4AA1F95129E5E54670F1! !
!CryptoTest methodsFor: 'private key' stamp: 'len 2/15/2003 11:02'!
genericARC4TestKey: key plaintext: plaintext ciphertext: ciphertext
	| vector rc4 |
	vector _ plaintext copy.
	rc4 _ ARC4 new.
	rc4 key: key.
	rc4 encrypt: vector.
	self assert: vector = ciphertext! !
!CryptoTest methodsFor: 'private key' stamp: 'len 2/15/2003 11:01'!
testARC4
	self genericARC4TestKey: #(16r01 16r23 16r45 16r67 16r89 16rAB 16rCD 16rEF) plaintext: #(16r01 16r23 16r45 16r67 16r89 16rAB 16rCD 16rEF) ciphertext: #(16r75 16rB7 16r87 16r80 16r99 16rE0 16rC5 16r96).
	self genericARC4TestKey: #(16r01 16r23 16r45 16r67 16r89 16rAB 16rCD 16rEF) plaintext: #(16r00 16r00 16r00 16r00 16r00 16r00 16r00 16r00) ciphertext: #(16r74 16r94 16rC2 16rE7 16r10 16r4B 16r08 16r79).
	self genericARC4TestKey: #(16r00 16r00 16r00 16r00 16r00 16r00 16r00 16r00) plaintext: #(16r00 16r00 16r00 16r00 16r00 16r00 16r00 16r00) ciphertext: #(16rDE 16r18 16r89 16r41 16rA3 16r37 16r5D 16r3A).
	self genericARC4TestKey: #(16rEF 16r01 16r23 16r45) plaintext: #(16r00 16r00 16r00 16r00 16r00 16r00 16r00 16r00 16r00 16r00) ciphertext: #(16rD6 16rA1 16r41 16rA7 16rEC 16r3C 16r38 16rDF 16rBD 16r61)! !
!CryptoTest methodsFor: 'private key' stamp: 'len 8/15/2002 01:58'!
testDES
	| plain key d |
	plain _ ByteArray new: 8.
	key _ ByteArray new: 8.
	#(16r01 16r23 16r45 16r67 16r89 16rAB 16rCD 16rE7) doWithIndex: [ :c :i |
		plain at: i put: c ].
	#(16r01 16r23 16r45 16r67 16r89 16rAB 16rCD 16rEF) doWithIndex: [
:c :i |
		key at: i put: c ].
	d _ DES key: key.
	d encryptBlock: plain.
	#(16rC9 16r57 16r44 16r25 16r6A 16r5E 16rD3 16r1D) doWithIndex: [
:c :i |
		self assert: c = (plain at: i) asInteger]! !
!CryptoTest methodsFor: 'private key' stamp: 'len 8/9/2002 13:23'!
testDES2
	| d plain key |
	plain _ 'Squeaker'.
	key _ 'Bite me!!'.
	d _ DES key: key.
	d encryptBlock: plain.
	#(254 141 73 104 43 44 242 206) doWithIndex: [ :c :i | self assert: c = ((plain at: i) asInteger)].
	d _ DES key: key.
	d decryptBlock: plain.
	self assert: plain = 'Squeaker'! !
!CryptoTest methodsFor: 'private key' stamp: 'len 10/25/2002 15:29'!
testRijndael
	| rijndael vector |
	rijndael _ Rijndael key: (0 to: 15) asByteArray.
	vector _ (0 to: 15) asByteArray.
	rijndael encryptBlock: vector.
	self assert: vector hex = '0A940BB5416EF045F1C39458C653EA5A'.
	rijndael decryptBlock: vector.
	self assert: vector hex = '000102030405060708090A0B0C0D0E0F'.

	rijndael _ Rijndael new blockSize: 16; keySize: 24.
	rijndael key: (0 to: 16r17) asByteArray.
	vector _ (0 to: 15) asByteArray.
	rijndael encryptBlock: vector.
	self assert: vector hex = '0060BFFE46834BB8DA5CF9A61FF220AE'.
	rijndael decryptBlock: vector.
	self assert: vector hex = '000102030405060708090A0B0C0D0E0F'.

	rijndael _ Rijndael new blockSize: 16; keySize: 32.
	rijndael key: (0 to: 16r1F) asByteArray.
	vector _ (0 to: 15) asByteArray.
	rijndael encryptBlock: vector.
	self assert: vector hex = '5A6E045708FB7196F02E553D02C3A692'.
	rijndael decryptBlock: vector.
	self assert: vector hex = '000102030405060708090A0B0C0D0E0F'! !
!CryptoTest methodsFor: 'private key' stamp: 'len 8/21/2002 16:30'!
testRijndael128128
	| key vector cipher |
	key _ #(16r2B 16r7E 16r15 16r16 16r28 16rAE 16rD2 16rA6 16rAB 16rF7 16r15 16r88 16r09 16rCF 16r4F 16r3C) asByteArray.
	vector _ #(16r32 16r43 16rF6 16rA8 16r88 16r5A 16r30 16r8D 16r31 16r31 16r98 16rA2 16rE0 16r37 16r07 16r34) asByteArray.

	cipher _ Rijndael key: key.
	cipher encryptBlock: vector.
	self assert: vector hex = '3925841D02DC09FBDC118597196A0B32'.
	cipher decryptBlock: vector.
	self assert: vector hex = '3243F6A8885A308D313198A2E0370734'! !
!CryptoTest methodsFor: 'public key' stamp: 'len 11/15/2002 22:58'!
dsaPrivateKey
	^ DSAPrivateKey
		p: 8343811888543852523216773185009428259187948644369498021763210776677854991854533186365944349987509452133156416880596803846631577352387751880552969116768071
		q: 1197175832754339660404549606408619548226315875117
		g: 1433467472198821951822151391684734233265646022897503720591270330985699984763922266163182803556189497900262038518780931942996381297743579119123094520048965
		x: 957348690772296812! !
!CryptoTest methodsFor: 'public key' stamp: 'len 11/15/2002 22:59'!
dsaPublicKey
	^ DSAPublicKey
		p: 8343811888543852523216773185009428259187948644369498021763210776677854991854533186365944349987509452133156416880596803846631577352387751880552969116768071
		q: 1197175832754339660404549606408619548226315875117
		g: 1433467472198821951822151391684734233265646022897503720591270330985699984763922266163182803556189497900262038518780931942996381297743579119123094520048965
		y: 4645213122572190617807944614677917601101008235397095646475699959851618402406173485853587185431290863173614335452934961425661774118334228449202337038283799! !
!CryptoTest methodsFor: 'public key' stamp: 'len 8/15/2002 01:38'!
genericRSATest: bits
	| generator public private msg c |
	generator _ RSAKeyPairGenerator new bits: bits.
	public _ generator publicKey. "this may take a while"
	private _ generator privateKey.

	msg _ 1234567890987654321. "the plaintext"
	
c _ public crypt: msg. "the ciphertext (print it and take a look)"
	self assert: (private crypt: c) = msg! !
!CryptoTest methodsFor: 'public key' stamp: 'len 11/15/2002 23:04'!
testDSASigningAndVerifying
	| msg sig |
	msg _ 'This is a test...'.
	sig _ self dsaPrivateKey signMessage: msg.
	self assert: (self dsaPublicKey verify: sig isSignatureOf: msg)! !
!CryptoTest methodsFor: 'public key' stamp: 'cs 12/5/2002 15:50'!
testElGamalEncryption
	| elgamal pub priv c |
	elgamal _ ElGamalKeyGenerator new.
	elgamal generateKeysOfSize: 15.
	pub _ elgamal publicKey.
	priv _ elgamal privateKey.
	c _ pub encryptElement: 31.
	self assert: (priv decryptElement: c) = 31.

! !
!CryptoTest methodsFor: 'public key' stamp: 'cs 12/5/2002 18:48'!
testElGamalSignature
	| elgamal pub priv signature |
	elgamal _ ElGamalKeyGenerator new.
	elgamal generateKeysOfSize: 15.
	pub _ elgamal publicKey.
	priv _ elgamal privateKey.
	signature _ priv signMessage: 'hello'.
	self assert: (pub verifySignature: signature onMessage: 'hello')! !
!CryptoTest methodsFor: 'public key' stamp: 'len 8/3/2002 21:46'!
testRSA128
	self genericRSATest: 128! !
!CryptoTest methodsFor: 'public key' stamp: 'len 8/3/2002 21:46'!
testRSA64
	self genericRSATest: 64! !
!CryptoTest methodsFor: 'others' stamp: 'len 10/26/2002 16:33'!
testDiffieHellman
	| alice bob fromAlice fromBob k1 k2 |
	alice _ DiffieHellman bits: 15.
	bob _ DiffieHellman prime: alice prime generator: alice generator.
	fromAlice _ alice sendMessage.
	fromBob _ bob sendMessage.
	k1 _ alice receiveMessage: fromBob.
	k2 _ bob receiveMessage: fromAlice.
	self assert: k1 = k2! !
!CryptoTest methodsFor: 'others' stamp: 'len 8/4/2002 00:44'!
testSecureRandom
	| random |
	random _ SecureRandom key: 'abcd'.
	100 timesRepeat: [self assert: (random nextBits: 1) <= 1].
	100 timesRepeat: [self assert: (random nextBits: 1024) highBit <= 1024]! !
!DES methodsFor: 'accessing' stamp: 'len 8/2/2002 03:14'!
decryptBlock: aByteArray
	encrypting = false ifFalse: [self key: key encrypt: false].
	self transform: aByteArray! !
!DES methodsFor: 'accessing' stamp: 'len 8/2/2002 03:15'!
encryptBlock: aByteArray
	encrypting = true ifFalse: [self key: key encrypt: true].
	self transform: aByteArray! !
!DES methodsFor: 'accessing' stamp: 'len 8/2/2002 15:03'!
key: aByteArray
	key _ aByteArray.
	encrypting _ nil! !
!DES methodsFor: 'private' stamp: 'len 8/2/2002 02:44'!
key: aByteArray encrypt: aBoolean
"	self primPluginAvailable ifFalse: [self error: 'DES plugin missing']."
	aByteArray size = 8 ifFalse: [self error: 'DES key must be 8 bytes'].
	cookedKey _ WordArray new: 32.
	cookedKey atAllPut: 0.
	self primCookKey: aByteArray mode: (aBoolean ifTrue: [1] ifFalse:
[0]) to: cookedKey! !
!DES methodsFor: 'private' stamp: 'DSM 1/25/2000 19:09'!
transform: aByteArray
	self primPluginAvailable ifFalse: [self error: 'DES plugin missing'].
	cookedKey ifNil: [ self error: 'DES key not provided'].
	cookedKey size = 32 ifFalse: [ self error: 'DES cooked key damaged'].
	aByteArray size = 8 ifFalse: [ self error: 'DES block must be 8
bytes'].
	self primTransform: aByteArray using: cookedKey

	! !
!DES methodsFor: 'primitives' stamp: 'len 7/27/2002 04:04'!
primCookKey: aByteArray mode: flag to: cooked
	<primitive: 'primitiveDESCookKey' module: 'DESPlugin'>
	^ self primitiveFailed

	! !
!DES methodsFor: 'primitives' stamp: 'len 7/27/2002 04:04'!
primPluginAvailable
	<primitive: 'primitiveDESPluginAvailable' module: 'DESPlugin'>
	^ true! !
!DES methodsFor: 'primitives' stamp: 'len 7/27/2002 04:04'!
primTransform: aByteArray using: cooked
	<primitive: 'primitiveDESTransform' module: 'DESPlugin'>
	^ self primitiveFailed! !
!DES class methodsFor: 'accessing' stamp: 'len 8/9/2002 13:12'!
blockSize
	^ 8! !
!DES class methodsFor: 'accessing' stamp: 'len 8/9/2002 13:12'!
keySize
	^ 8! !
!DESPlugin methodsFor: 'support' stamp: 'DSM 1/24/2000 23:32'!
checkedBytePtrOf: oop
	"Return the first indexable word of oop which is assumed to be
variableByteSubclass"
	self returnTypeC:'unsigned char *'.
	interpreterProxy success: (interpreterProxy isBytes: oop).
	^self cCoerce: (interpreterProxy firstIndexableField: oop) to:
'unsigned char *'
! !
!DESPlugin methodsFor: 'support' stamp: 'DSM 1/24/2000 23:32'!
checkedWordPtrOf: oop
	"Return the first indexable word of oop which is assumed to be
variableWordSubclass"
	self returnTypeC:'unsigned long *'.
	interpreterProxy success: (interpreterProxy isWords: oop).
	^self cCoerce: (interpreterProxy firstIndexableField: oop) to:
'unsigned long *'
! !
!DESPlugin methodsFor: 'support' stamp: 'DSM 1/25/2000 23:01'!
cookKey: rawPtr to: cookPtr
	"preprocess the key to more useful format"

	| raw0 raw1 cook |
	self var: 'cook' declareC: 'unsigned long cook'.
	self var: 'cookPtr' declareC: 'unsigned long *cookPtr'. "32 words"
	self var: 'rawPtr' declareC: 'unsigned long *rawPtr'. "32 words"
	self var: 'raw0' declareC: 'unsigned long raw0'.
	self var: 'raw1' declareC: 'unsigned long raw1'.
	0 to: 15 do: [ :i |
		raw0 _ rawPtr at: i*2.
		raw1 _ rawPtr at: i*2 + 1.
		cook _ (raw0 bitAnd: 16r00FC0000) << 6.
		cook _ cook bitOr: (raw0 bitAnd: 16r00000FC0) << 10.
		cook _ cook bitOr: (raw1 bitAnd: 16r00FC0000) >> 10.
		cook _ cook bitOr: (raw1 bitAnd: 16r00000FC0) >> 6.
		cookPtr at: (i * 2) put: cook.
		cook _ (raw0 bitAnd: 16r0003F000) << 12.
		cook _ cook bitOr: (raw0 bitAnd: 16r0000003F) << 16.
		cook _ cook bitOr: (raw1 bitAnd: 16r0003F000) >> 4.
		cook _ cook bitOr: (raw1 bitAnd: 16r0000003F).
		cookPtr at: (i*2+1) put: cook.
		].

! !
!DESPlugin methodsFor: 'support' stamp: 'DSM 1/26/2000 16:35'!
encrypt: dataPtr with: key
	| fVal work right left |
	self var: 'dataPtr' declareC: 'unsigned long *dataPtr'.
	self var: 'key' declareC: 'unsigned long *key'.
	self var: 'fVal' declareC: 'unsigned long fVal'.
	self var: 'work' declareC: 'unsigned long work'.
	self var: 'right' declareC: 'unsigned long right'.
	self var: 'left' declareC: 'unsigned long left'.

	left _ dataPtr at: 0.
	right _ dataPtr at: 1.

	"perform required but otherwise pointless bit twizzling"
	work _ ((left >> 4) bitXor: right) bitAnd: 16r0F0F0F0F.
	right _ right bitXor: work.
	left _ left bitXor: (work << 4).
	work _ ((left >> 16) bitXor: right) bitAnd: 16r0000FFFF.
	right _ right bitXor: work.
	left _ left bitXor: (work << 16).
	work _ ((right >> 2) bitXor: left) bitAnd: 16r33333333.
	left _ left bitXor: work.
	right _ right bitXor: (work << 2).
	work _ ((right >> 8) bitXor: left) bitAnd: 16r00FF00FF.
	left _ left bitXor: work.
	right _ right bitXor: (work << 8).
	right _ ((right << 1) bitOr: ((right >> 31) bitAnd: 1)) bitAnd: 16rFFFFFFFF.
	work _ (left bitXor: right) bitAnd: 16rAAAAAAAA.
	left _ left bitXor: work.
	right _ right bitXor: work.
	left _ ((left << 1) bitOr: ((left >> 31) bitAnd: 1)) bitAnd:
16rFFFFFFFF.

	"perform the 8 rounds of real encryption"
	0 to: 28 by: 4 do: [ :round |
		work _ right << 28 bitOr: right >> 4.
		work _ work bitXor: (key at: round).
		fVal _ sp7 at: (work bitAnd: 16r3F).
		fVal _ fVal bitOr: (sp5 at: (work >> 8 bitAnd: 16r3F)).
		fVal _ fVal bitOr: (sp3 at: (work >> 16 bitAnd: 16r3F)).
		fVal _ fVal bitOr: (sp1 at: (work >> 24 bitAnd: 16r3F)).

		work _ right bitXor: (key at: round+1).
		fVal _ fVal bitOr: (sp8 at: (work bitAnd: 16r3F)).
		fVal _ fVal bitOr: (sp6 at: (work >> 8 bitAnd: 16r3F)).
		fVal _ fVal bitOr: (sp4 at: (work >> 16 bitAnd: 16r3F)).
		fVal _ fVal bitOr: (sp2 at: (work >> 24 bitAnd: 16r3F)).
		left _ left bitXor: fVal.

		work _ left << 28 bitOr: left >> 4.
		work _ work bitXor: (key at: round+2).
		fVal _ sp7 at: (work bitAnd: 16r3F).
		fVal _ fVal bitOr: (sp5 at: (work >> 8 bitAnd: 16r3F)).
		fVal _ fVal bitOr: (sp3 at: (work >> 16 bitAnd: 16r3F)).
		fVal _ fVal bitOr: (sp1 at: (work >> 24 bitAnd: 16r3F)).

		work _ left bitXor: (key at: round+3).
		fVal _ fVal bitOr: (sp8 at: (work bitAnd: 16r3F)).
		fVal _ fVal bitOr: (sp6 at: (work >> 8 bitAnd: 16r3F)).
		fVal _ fVal bitOr: (sp4 at: (work >> 16 bitAnd: 16r3F)).
		fVal _ fVal bitOr: (sp2 at: (work >> 24 bitAnd: 16r3F)).
		right _ right bitXor: fVal.
		].

	"undo the pointless twizzling"
	right _ right<<31 bitOr: right>>1.
	work _ (left bitXor: right) bitAnd: 16rAAAAAAAA.
	left _ left bitXor: work.
	right _ right bitXor: work.
	left _ left<<31 bitOr: left>>1.
	work _ (left>>8 bitXor: right) bitAnd: 16r00FF00FF.
	right _ right bitXor: work.
	left _ left bitXor: work<<8.
	work _ (left >> 2 bitXor: right) bitAnd: 16r33333333.
	right _ right bitXor: work.
	left _ left bitXor: work<<2.
	work _ (right>>16 bitXor: left) bitAnd: 16r0000FFFF.
	left _ left bitXor: work.
	right _ right bitXor: work<<16.
	work _(right>>4 bitXor: left) bitAnd: 16r0F0F0F0F.
	left _ left bitXor: work.
	right _ right bitXor: work<<4.

	dataPtr at: 0 put: right.
	dataPtr at: 1 put: left.

	! !
!DESPlugin methodsFor: 'support' stamp: 'DSM 1/26/2000 00:32'!
processKey: keyPtr mode: encode to: cookedPtr
	| l m n pc1m pcr rawKey |
	self var: 'cookedPtr' declareC: 'unsigned long *cookedPtr'.
	self var: 'keyPtr' declareC: 'unsigned char *keyPtr'.
	self var: 'pc1m' declareC: 'unsigned char pc1m[56]'.
	self var: 'pcr' declareC: 'unsigned char pcr[56]'.
	self var: 'rawKey' declareC: 'unsigned long rawKey[32]'.
	self cCode: '/* Who is Keyser Soze? */' inSmalltalk: [pcr _ 1. pc1m
_ 1. rawKey _ 1].
	0 to: 55 do: [ :j |
		l _ pc1 at: j.
		m _ l bitAnd: 7.
		((((keyPtr at: (l >> 3)) bitAnd: (byteBit at: m))) ~= 0)
			ifTrue: [ pc1m at: j put: 1 ]
			ifFalse: [ pc1m at: j put: 0].
		].
	0 to: 15 do: [ :i |
		encode ifFalse: [ m _ 15 - i << 1] ifTrue: [m _ i << 1].
		n _ m + 1.
		rawKey at: m put: (rawKey at: n put: 0).
		0 to: 27 do: [ :j |
			l _ j + (totRot at: i).
			l<28 ifTrue: [pcr at: j put: (pc1m at: l)] ifFalse:
[pcr at: j put: (pc1m at: l-28)].
			].
		28 to: 55 do: [ :j |
			l _ j + (totRot at: i).
			l<56 ifTrue: [pcr at: j put: (pc1m at: l)] ifFalse:
[pcr at: j put: (pc1m at: l-28)].
			].
		0 to: 23 do: [ :j |
			(pcr at: (pc2 at: j)) ~= 0 ifTrue:
				[rawKey at: m put: ((rawKey at: m) bitOr:
(bigByte at: j))].
			(pcr at: (pc2 at: j+24)) ~= 0 ifTrue:
				[rawKey at: n put: ((rawKey at: n) bitOr:
(bigByte at: j))].
			].
		].
	self cookKey: rawKey to: cookedPtr! !
!DESPlugin methodsFor: 'support' stamp: 'DSM 1/25/2000 00:28'!
scrunch: bytePtr to: wordPtr
	self var: 'bytePtr' declareC: 'unsigned char *bytePtr'.
	self var: 'wordPtr' declareC: 'unsigned long *wordPtr'.
	wordPtr at: 0 put:
		(bytePtr at: 0) << 24 +
		((bytePtr at: 1) << 16) +
		((bytePtr at: 2) << 8) +
		(bytePtr at: 3).
	wordPtr at: 1 put:
		(bytePtr at: 4) << 24 +
		((bytePtr at: 5) << 16) +
		((bytePtr at: 6) << 8) +
		(bytePtr at: 7)! !
!DESPlugin methodsFor: 'support' stamp: 'DSM 1/25/2000 00:31'!
unscrunch: wordPtr to: bytePtr
	self var: 'bytePtr' declareC: 'unsigned char *bytePtr'.
	self var: 'wordPtr' declareC: 'unsigned long *wordPtr'.
	bytePtr at: 0 put: (((wordPtr at: 0)>>24) bitAnd: 16rFF).
	bytePtr at: 1 put: (((wordPtr at: 0)>>16) bitAnd: 16rFF).
	bytePtr at: 2 put: (((wordPtr at: 0)>>8) bitAnd: 16rFF).
	bytePtr at: 3 put: ((wordPtr at: 0) bitAnd: 16rFF).
	bytePtr at: 4 put: (((wordPtr at: 1)>>24) bitAnd: 16rFF).
	bytePtr at: 5 put: (((wordPtr at: 1)>>16) bitAnd: 16rFF).
	bytePtr at: 6 put: (((wordPtr at: 1)>>8) bitAnd: 16rFF).
	bytePtr at: 7 put: ((wordPtr at: 1) bitAnd: 16rFF).
! !
!DESPlugin methodsFor: 'primitives' stamp: 'DSM 1/25/2000 23:04'!
primitiveDESCookKey
	"preprocess the key to more useful format

	param1 = raw key: ByteArray[8]
	param2 = 1->encode 0->decode
	param3 = cooked key:  WordArray[32]"

	| raw cooked encode |
	self export: true.
	self var: 'raw' declareC: 'unsigned char *raw'.
	self var: 'cooked' declareC: 'unsigned long *cooked'.
	interpreterProxy methodArgumentCount = 3
		ifFalse:[^interpreterProxy primitiveFail].
	raw _ self checkedBytePtrOf: (interpreterProxy stackValue: 2).
	encode _ interpreterProxy stackIntegerValue: 1.
	cooked _ self checkedWordPtrOf: (interpreterProxy stackValue: 0).
	interpreterProxy failed
		ifTrue: [ ^nil ].
	self processKey: raw mode: encode to: cooked.
	interpreterProxy pop: 3
	! !
!DESPlugin methodsFor: 'primitives' stamp: 'DSM 1/25/2000 18:30'!
primitiveDESPluginAvailable
	self export: true.
	interpreterProxy pop: 1.
	interpreterProxy pushBool: true
! !
!DESPlugin methodsFor: 'primitives' stamp: 'DSM 1/25/2000 18:19'!
primitiveDESTransform
	"encrypt/decrypt some data

	param1 = data key: ByteArray[8]
	param2 = cooked key:  WordArray[32]"

	| data work cooked |
	self export: true.
	self var: 'data' declareC: 'unsigned char *data'.
	self var: 'cooked' declareC: 'unsigned long *cooked'.
	self var: 'work' declareC: 'unsigned long work[2]'.
	self cCode: '/* Hi ho, Hi ho...*/' inSmalltalk: [work _ 1].
	interpreterProxy methodArgumentCount = 2
		ifFalse:[^interpreterProxy primitiveFail].
	data _ self checkedBytePtrOf: (interpreterProxy stackValue: 1).
	cooked _ self checkedWordPtrOf: (interpreterProxy stackValue: 0).
	interpreterProxy failed
		ifTrue: [ ^nil ].
	self scrunch: data to: work.
	self encrypt: work with: cooked.
	self unscrunch: work to: data.
	interpreterProxy pop: 2
	! !
!DESPlugin class methodsFor: 'translation' stamp: 'DSM 1/26/2000 00:06'!
declareCVarsIn: cg
	cg var: 'byteBit' declareC: 'unsigned short byteBit[8] = {
128,64,32,16,8,4,2,1 }'.
	cg var: 'bigByte' declareC:
		(String streamContents:[:s|
			s nextPutAll:'unsigned long bigByte[24] = { '.
			23 to: 0 by: -1 do: [ :i |
				s nextPutAll: (1<<i) asString, ','].
			s nextPutAll:' }']).
	cg var: 'pc1' declareC: 'unsigned char pc1[56] = {
		56, 48, 40, 32, 24, 16,  8,	 0, 57, 49, 41, 33, 25, 17,
		 9,  1, 58, 50, 42, 34, 26,	18, 10,  2, 59, 51, 43, 35,
		62, 54, 46, 38, 30, 22, 14,	 6, 61, 53, 45, 37, 29, 21,
		13,  5, 60, 52, 44, 36, 28,	20, 12,  4, 27, 19, 11,  3 }'.
	cg var: 'pc2' declareC: 'unsigned char pc2[48] = {
		13, 16, 10, 23,  0,  4,	 2, 27, 14,  5, 20,  9,
		22, 18, 11,  3, 25,  7,	15,  6, 26, 19, 12,  1,
		40, 51, 30, 36, 46, 54,	 29, 39, 50, 44, 32, 47,
		43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }'.
	cg var: 'totRot' declareC:
'unsigned char totRot[16] = { 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 }'.
	cg var: 'sp1' declareC: 'unsigned long sp1[64] = {
		0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
		0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
		0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
		0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
		0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
		0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
		0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
		0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
		0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
		0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
		0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
		0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
		0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
		0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
		0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
		0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L }'.
	cg var: 'sp2' declareC: 'unsigned long sp2[64] = {
		0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
		0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
		0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
		0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
		0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
		0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
		0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
		0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
		0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
		0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
		0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
		0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
		0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
		0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
		0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
		0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L }'.
	cg var: 'sp3' declareC: 'unsigned long sp3[64] = {
		0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
		0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
		0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
		0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
		0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
		0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
		0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
		0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
		0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
		0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
		0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
		0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
		0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
		0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
		0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
		0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L }'.
	cg var: 'sp4' declareC: 'unsigned long sp4[64] = {
		0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
		0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
		0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
		0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
		0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
		0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
		0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
		0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
		0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
		0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
		0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
		0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
		0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
		0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
		0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
		0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L }'.
	cg var: 'sp5' declareC: 'unsigned long sp5[64] = {
		0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
		0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
		0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
		0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
		0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
		0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
		0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
		0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
		0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
		0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
		0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
		0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
		0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
		0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
		0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
		0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L }'.
	cg var: 'sp6' declareC: 'unsigned long sp6[64] = {
		0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
		0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
		0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
		0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
		0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
		0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
		0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
		0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
		0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
		0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
		0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
		0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
		0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
		0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
		0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
		0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L }'.
	cg var: 'sp7' declareC: 'unsigned long sp7[64] = {
		0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
		0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
		0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
		0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
		0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
		0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
		0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
		0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
		0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
		0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
		0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
		0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
		0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
		0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
		0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
		0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L }'.
	cg var: 'sp8' declareC: 'unsigned long sp8[64] = {
		0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
		0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
		0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
		0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
		0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
		0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
		0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
		0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
		0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
		0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
		0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
		0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
		0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
		0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
		0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
		0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L }'.


! !
!DSAKeyPairGenerator methodsFor: 'as yet unclassified' stamp: 'rww 10/21/2002 19:59'!
generateKeySet
	"Generate and answer a key set for DSA. The result is a pair (<private key><public key>). Each key is an array of four large integers. The private key is (p, q, g, x); the public one is (p, q, g, y). The signer must be sure to record (p, q, g, x), and must keep x secret to prevent someone from forging their signature."
	"Note: Key generation can take some time. Open a transcript so you can see what's happening and take a coffee break!!"

	| exp h |
	random _ SecureRandom new.
	self generateQandP.
	exp _ (p - 1) / q.
	h _ 2.
	[g _ h raisedTo: exp modulo: p. g = 1] whileTrue: [h _ h + 1].
	x _ self nextRandom160.
	y _ g raisedTo: x modulo: p.
! !
!DSAKeyPairGenerator methodsFor: 'as yet unclassified' stamp: 'len 10/25/2002 15:14'!
generateQandP
	"Generate the two industrial-grade primes, q (160-bits) and p (512-bit) needed to build a key set. Answer the array (q, p, s), where s is the seed that from which q and p were created. This seed is normally discarded, but can be used to verify the key generation process if desired."

	| pBits halfTwoToTheP chunkCount twoQ n c w |
	pBits _ 512.  "desired size of p in bits"
	halfTwoToTheP _ 2 raisedTo: (pBits - 1).
	chunkCount _ pBits // 160.

	Transcript show: 'Searching for primes q and p...'; cr.
	[true] whileTrue: [
		Transcript show: '  Found a candidate q.'; cr.
		q _ random nextBits: 160.
		q _ q bitOr: 1. "ensure it is odd"
		q _ q bitOr: 1 << 160. "ensure it is of the requiered length"
		q _ (PrimesFinder candidate: q) nextPrime.
		twoQ _ q bitShift: 1.
		n _ 2.
		c _ 0.
		[c < 4096] whileTrue: [
			w _ random nextBits: pBits.
			x _ w + halfTwoToTheP.
			p _ (x - ( x \\ twoQ)) + 1.
			p highBit = pBits ifTrue: [
				Transcript show: '    Testing potential p ', (c + 1) printString, '...'; cr.
				(self isProbablyPrime: p) ifTrue: [
					Transcript show: '  Found p!!'; cr.
					^ self]].
			n _ n + chunkCount + 1.
			c _ c + 1]]! !
!DSAKeyPairGenerator methodsFor: 'as yet unclassified' stamp: 'len 8/15/2002 02:23'!
privateKey
	^ DSAPrivateKey p: p q: q g: g x: x! !
!DSAKeyPairGenerator methodsFor: 'as yet unclassified' stamp: 'len 8/15/2002 02:24'!
publicKey
	^ DSAPublicKey p: p q: q g: g y: y! !
!DSAPlugin methodsFor: 'primitives-SHA' stamp: 'jm 12/21/1999 22:52'!
primitiveExpandBlock
	"Expand a 64 byte ByteArray (the first argument) into and an Bitmap of 80 32-bit words (the second argument). When reading a 32-bit integer from the ByteArray, consider the first byte to contain the most significant bits of the word (i.e., use big-endian byte ordering)."

	| expanded buf wordPtr bytePtr src v |
	self export: true.
	self var: #wordPtr declareC: 'unsigned int *wordPtr'.
	self var: #bytePtr declareC: 'unsigned char *bytePtr'.

	expanded _ interpreterProxy stackObjectValue: 0.
	buf _ interpreterProxy stackObjectValue: 1.
	interpreterProxy success: (interpreterProxy isWords: expanded).
	interpreterProxy success: (interpreterProxy isBytes: buf).
	interpreterProxy failed ifTrue: [^ nil].

	interpreterProxy success: ((interpreterProxy stSizeOf: expanded) = 80).
	interpreterProxy success: ((interpreterProxy stSizeOf: buf) = 64).
	interpreterProxy failed ifTrue: [^ nil].

	wordPtr _ interpreterProxy firstIndexableField: expanded.
	bytePtr _ interpreterProxy firstIndexableField: buf.

	src _ 0.
	0 to: 15 do: [:i |
		v _ ((bytePtr at: src) << 24) +
			((bytePtr at: src + 1) << 16) +
			((bytePtr at: src + 2) << 8) +
			(bytePtr at: src + 3).
		wordPtr at: i put: v.
		src _ src + 4].

	16 to: 79 do: [:i |
		v _ (((wordPtr at: i - 3) bitXor:
			 (wordPtr at: i - 8)) bitXor:
			 (wordPtr at: i - 14)) bitXor:
			 (wordPtr at: i - 16).
		v _ self leftRotate: v by: 1.
		wordPtr at: i put: v].

	interpreterProxy pop: 2.
! !
!DSAPlugin methodsFor: 'primitives-SHA' stamp: 'jm 12/21/1999 20:43'!
primitiveHasSecureHashPrimitive
	"Answer true if the secure hash primitive is implemented."

	self export: true.
	interpreterProxy pop: 1.
	interpreterProxy pushBool: true.
! !
!DSAPlugin methodsFor: 'primitives-SHA' stamp: 'jm 12/21/1999 23:35'!
primitiveHashBlock
	"Hash a Bitmap of 80 32-bit words (the first argument), using the given state (the second argument)."

	| state buf statePtr bufPtr a b c d e tmp |
	self export: true.
	self var: #statePtr declareC: 'unsigned int *statePtr'.
	self var: #bufPtr declareC: 'unsigned int *bufPtr'.

	state _ interpreterProxy stackObjectValue: 0.
	buf _ interpreterProxy stackObjectValue: 1.
	interpreterProxy success: (interpreterProxy isWords: state).
	interpreterProxy success: (interpreterProxy isWords: buf).
	interpreterProxy failed ifTrue: [^ nil].

	interpreterProxy success: ((interpreterProxy stSizeOf: state) = 5).
	interpreterProxy success: ((interpreterProxy stSizeOf: buf) = 80).
	interpreterProxy failed ifTrue: [^ nil].

	statePtr _ interpreterProxy firstIndexableField: state.
	bufPtr _ interpreterProxy firstIndexableField: buf.

	a _ statePtr at: 0.
	b _ statePtr at: 1.
	c _ statePtr at: 2.
	d _ statePtr at: 3.
	e _ statePtr at: 4.
 
	0 to: 19 do: [:i |
		tmp _ 16r5A827999 + ((b bitAnd: c) bitOr: (b bitInvert32 bitAnd: d)) +
				(self leftRotate: a by: 5) +  e + (bufPtr at: i).
		e _ d.  d _ c.  c _ self leftRotate: b by: 30.  b _ a.  a _ tmp].

	20 to: 39 do: [:i |
		tmp _ 16r6ED9EBA1 + ((b bitXor: c) bitXor: d) +
				(self leftRotate: a by: 5) +  e + (bufPtr at: i).
		e _ d.  d _ c.  c _ self leftRotate: b by: 30.  b _ a.  a _ tmp].

	40 to: 59 do: [:i |
		tmp _ 16r8F1BBCDC + (((b bitAnd: c) bitOr: (b bitAnd: d)) bitOr: (c bitAnd: d)) +
				(self leftRotate: a by: 5) +  e + (bufPtr at: i).
		e _ d.  d _ c.  c _ self leftRotate: b by: 30.  b _ a.  a _ tmp].

	60 to: 79 do: [:i |
		tmp _ 16rCA62C1D6 + ((b bitXor: c) bitXor: d) +
				(self leftRotate: a by: 5) +  e + (bufPtr at: i).
		e _ d.  d _ c.  c _ self leftRotate: b by: 30.  b _ a.  a _ tmp].

	statePtr at: 0 put: (statePtr at: 0) + a.
	statePtr at: 1 put: (statePtr at: 1) + b.
	statePtr at: 2 put: (statePtr at: 2) + c.
	statePtr at: 3 put: (statePtr at: 3) + d.
	statePtr at: 4 put: (statePtr at: 4) + e.

	interpreterProxy pop: 2.
! !
!DSAPlugin methodsFor: 'primitives-integers' stamp: 'jm 12/21/1999 18:48'!
primitiveBigDivide
	"Called with three LargePositiveInteger arguments, rem, div, quo. Divide div into rem and store the quotient into quo, leaving the remainder in rem."
	"Assume: quo starts out filled with zeros."

	| rem div quo |
	self export: true.
	quo _ interpreterProxy stackObjectValue: 0.
	div _ interpreterProxy stackObjectValue: 1.
	rem _ interpreterProxy stackObjectValue: 2.

	interpreterProxy success:
		(interpreterProxy fetchClassOf: rem) = interpreterProxy classLargePositiveInteger.
	interpreterProxy success:
		(interpreterProxy fetchClassOf: div) = interpreterProxy classLargePositiveInteger.
	interpreterProxy success:
		(interpreterProxy fetchClassOf: quo) = interpreterProxy classLargePositiveInteger.
	interpreterProxy failed ifTrue:[^ nil].

	dsaRemainder _ interpreterProxy firstIndexableField: rem.
	dsaDivisor _ interpreterProxy firstIndexableField: div.
	dsaQuotient _ interpreterProxy firstIndexableField: quo.

	divisorDigitCount _ interpreterProxy stSizeOf: div.
	remainderDigitCount _ interpreterProxy stSizeOf: rem.

	"adjust pointers for base-1 indexing"
	dsaRemainder _ dsaRemainder - 1.
	dsaDivisor _ dsaDivisor - 1.
	dsaQuotient _ dsaQuotient - 1.

	self bigDivideLoop.
	interpreterProxy pop: 3.
! !
!DSAPlugin methodsFor: 'primitives-integers' stamp: 'jm 12/21/1999 08:09'!
primitiveBigMultiply
	"Multiple f1 by f2, placing the result into prod. f1, f2, and prod must be LargePositiveIntegers, and the length of prod must be the sum of the lengths of f1 and f2."
	"Assume: prod starts out filled with zeros"

	| prod f2 f1 prodLen f1Len f2Len prodPtr f2Ptr f1Ptr digit carry k sum |
	self export: true.
	self var: #prodPtr declareC: 'unsigned char *prodPtr'.
	self var: #f2Ptr declareC: 'unsigned char *f2Ptr'.
	self var: #f1Ptr declareC: 'unsigned char *f1Ptr'.

	prod _ interpreterProxy stackObjectValue: 0.
	f2 _ interpr