Cryptographic API Functions/en: Unterschied zwischen den Versionen

Aus expecco Wiki (Version 2.x)
Zur Navigation springen Zur Suche springen
 
(43 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
Reference: [http://live.exept.de/ClassDoc/classDocOf:,MD5Stream MD5Stream]
All algorithms are accessed the same way, by either sending one of the convenient utility messages to a hash-stream-class, or by instantiating a hash stream and sending it the data to be hashed.
inherits from: [http://live.exept.de/ClassDoc/classDocOf:,HashStream HashStream]


[[Useful API Functions | Back to Useful API Functions]]
The utility messages are easier to use, but require the data to be hashed to be already present. The instance messages allow for streams of unknown length to be hashed, to preinitialize the parameters and to fetch/reset the hash value during the operation.


= Hashing =
Available hash classes are: <code>MD5Stream</code>, <code>SHA1Stream</code>, <code>SHA256Stream</code> etc.
All hash algorithms are accessed the same way, by either sending one of the convenient utility messages to a hash-stream-class, or by instantiating a hash stream and sending it the data to be hashed (byte-wise or block-wise).
(open a browser or evaluate "HashStream allSubclasses" to see them all).


The utility messages are easier to use, but require the hhash data to be already present in a byte- or character collection (i.e. in memory), which may be inefficient or impossible, if big chunks are to be hashed.
=== Utility ===


The instance messages allow for streams of unknown length to be hashed, to preinitialize the parameters and to fetch/reset the hash value during the operation.
''HashStreamClass'' <code>hashValueOf:</code> ''aStringOrByteArray''

Available hash classes are (among many others): <code>MD5Stream</code>, <code>SHA1Stream</code>, <code>SHA256Stream</code>, <code>SHA512Stream</code>, <code>RipeMD160Stream</code>, <code>SipHashStream</code>, <code>WhirlpoolStream</code> etc.

Open a class browser or evaluate "<code>HashStream allSubclasses inspect</code>" to see them all.
<br>eXept may provide additional hash classes upon request.

=== Class-Side Utility Protocol ===

:''HashStreamClass'' '''hashValueOf:''' ''aStringOrByteArray''
::Returns the hash value as a byte vector (the length of the vector depends on the algorithm).
::Returns the hash value as a byte vector (the length of the vector depends on the algorithm).
::Example:
::Example:
<div style="margin-left: 2em;">
<div style="margin-left: 4em;">
<code>MD5Stream hashValueOf:</code> 'hello world'
<code>MD5Stream hashValueOf:</code> 'hello world'
=> #[94 182 59 187 224 30 238 208 147 203 34 187 143 90 205 195]
<small>=> #[94 182 59 187 224 30 238 208 147 203 34 187 143 90 205 195]</small>
<code>SHA1Stream hashValueOf:</code> 'hello world'
<code>SHA1Stream hashValueOf:</code> 'hello world'
=> #[42 174 108 53 201 79 207 180 21 219 233 95 64 139 156 233 30 232 70 237]
<small>=> #[42 174 108 53 201 79 207 180 21 219 233 95 64 139 156 233 30 232 70 237]</small>
<code>SHA256Stream hashValueOf:</code> 'hello world'
<code>SHA256Stream hashValueOf:</code> 'hello world'
=> #[185 77 39 185 147 77 62 8 165 46 82 215 218 125 171 250 196
<small>=> #[185 77 39 185 147 77 62 8 165 46 82 215 218 125 171 250 196
132 239 227 122 83 128 238 144 136 247 172 226 239 205 233]
132 239 227 122 83 128 238 144 136 247 172 226 239 205 233]</small>
</div>
</div>


''HashStreamClass'' <code>hashValueHexString:</code> ''aStringOrByteArray''
:''HashStreamClass'' '''hashValueHexString:''' ''aStringOrByteArray''
::Returns the hash value as a hex string.
::Returns the hash value as a hex string.
::Example:
::Example:
<div style="margin-left: 2em;">
<div style="margin-left: 4em;">
<code>MD5Stream hashValueHexString:</code> 'hello world'
<code>MD5Stream hashValueHexString:</code> 'hello world'
=> '5eb63bbbe01eeed093cb22bb8f5acdc3'
<small>=> '5eb63bbbe01eeed093cb22bb8f5acdc3'</small>
<code>SHA1Stream hashValueHexString:</code> 'hello world'
<code>SHA1Stream hashValueHexString:</code> 'hello world'
=> '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'
<small>=> '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'</small>
<code>SHA256Stream hashValueHexString:</code> 'hello world'
<code>SHA256Stream hashValueHexString:</code> 'hello world'
=> 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'
<small>=> 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'</small>
</div>
</div>

:''HashStreamClass'' '''hashValueOfFile:''' ''aFilename''
::Returns the hash of a file's contents.
::Example:
<div style="margin-left: 4em;">
<code>MD5Stream hashValueOfFile:</code> 'Makefile'
<code>SHA256Stream hashValueOfFile:</code> 'Makefile'
<code>(SHA256Stream hashValueOfFile:</code> 'Makefile') hexPrintString
<code>(SHA256Stream hashValueOfFile:</code> 'Makefile') hexPrintString asLowercase
</div>

=== Instance Protocol ===

More fine control is available by instantiating a hash-stream and sending it the data.
First, create an instance:

myHashStream := ''HashStreamClass'' <code>new</code>.

then send it the bytes to be hashed with the usual stream messages:

myHashStream nextPutAll: ''stringOrByteCollection''
myHashStream nextPut: ''characterOrSingleByteValue''

and finally ask the stream for its current (running) hashValue with:

myHashStream hashValue

Thus, the above utility in the MD5Stream is equivalent to:

myStream := MD5Stream new.
myStream nextPutAll:'hello world'.
hashBytes := myStream hashValue.
hashHexString := myStream hashValue hexPrintString asLowercase.

= Encryption & Decryption =

This is done by instantiating a cipher, defining the block-chaining mode and streaming data blocks to it. The way to setup the cipher may differ between the individual algorithms: some require a key only, others require more parameters (e.g. an init vector).

Notice that the raw cipher instance operates in ecb mode, which is very insecure.
Send one of the mode messages to define the block chaining mode (ofb, cfg, ctr, etc.)

=== Common Cipher Class Protocol ===
All Cipher classes can be asked for the keySize and blockSize:

:''aCipherClass'' '''keySize'''
::the length of the key (in bytes). If it supports multiple keySizes, the ''preferred'' or typical size is returned.

:''aCipherClass'' '''keySizes'''
::a collection of supported key sizes. If the cipher supports only one keySize, the collection will contain only one element.

:''aCipherClass'' '''blockSize'''
::blocks of data are encrypted/decrypted in multiples of the blockSize.
::Depending on the block chaining mode, data may have to be passed to the cipher in multiples of that size.

:''aCipherClass'' '''blockSizes'''
::a collection of supported block sizes.

=== Common BlockCipher Instance Protocol ===

:''aCipher'' '''ofb'''
::returns an object which implements the output feedback mode on top of the cipher. ::Supports the same stream protocol as the cipher. The message length is not required to be a multiple of the cipher's block size.

:''aCipher'' '''ctr'''
::similar for counter mode. The message length is not required to be a multiple of the cipher's block size.

:''aCipher'' '''cbc'''
::similar for cipher block chaining mode. The message length must be a multiple of the cipher's block size.

:''aCipher'' '''cfb'''
::similar for cipher feedback mode. The message length is not required to be a multiple of the cipher's block size.

=== DES Cipher ===

In basic ECB mode (attention: insecure!!):

key := #[12 34 56 78 90 12 34 56].
cipher := DesCipher new.
cipher key: key.
encrypted := cipher encrypt: 'hello world'.
...
decrypted := cipher decrypt: encrypted.

in CFB mode:
key := #[12 34 56 78 90 12 34 56].
cipher := DesCipher new cfb.
cipher key: key.
encrypted := cipher encrypt: 'hello world'.
...
decrypted := cipher decrypt: encrypted.

=== Tea Cipher ===

In basic ECB mode (attention: insecure!):

key := '00112233445566778899aabbccddeeff'.
cipher := TeaCipher new.
cipher key: key.
encrypted := cipher encrypt: 'hello world'.
...
decrypted := cipher decrypt: encrypted.

In OFB (output feedback block mode) mode:
...
cipher := TeaCipher new ofb.
cipher key: key.
cipher initialVector:#[1 2 3 4 5 6 7 8].
...

=== Others... ===
Many more ciphers are available; open a browser or evaluate "<code>Cipher allSubclasses inspect</code>" in a workspace.

= Certificate Handling =

=== Reading from a PEM File ===

Use <code>fromPemStream:</code> to convert a PEM file.
cert := X509Certificate fromPemStream:('file.pem' asFilename readStream)

This method can also read a string in case the PEM is already available:
cert := X509Certificate fromPemStream:'
-----BEGIN CERTIFICATE-----
MIIHBTCCBO2gAwIBAgIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJERTEa
MBgGA1UEChMRRXhlcHQgU29mdHdhcmUgQUcxEDAOBgNVBAsTB1Rlc3RpbmcxFzAV
...
vthHg54SuEay1ge+PvggvOqvMB4laWakbA==
-----END CERTIFICATE-----
'.

=== Writing as a PEM File ===

'filename.pem' asFilename writeStream
nextPutAll:cert asSignedPemString;
close.

=== Writing as a DER Encoded File ===
'filename.crt' asFilename writeStream
binary;
nextPutAll:caCert asSignedDerBytes;
close.
or more convenient:
'filename.crt' asFilename contents:(caCert asSignedDerBytes)

=== Creation ===

To create a self-signed certificate,
cert := X509CaCertificate new
subjectNameString:'C=DE, O=MyCompany, CN=Test';
issuerNameString:'C=DE, O= MyCompany, CN=Test-CA';
serialNumber:4711;
signatureAlgorithmNameString:#sha256WithRSAEncryption;
startValidity:Timestamp now;
endValidity:(Date today + 365) asTimestamp;
key:(RSASecretCryptKey
generateKeyLength:4096
publicExponent:65537
rng:RandomGenerator new);
signSelf

Supported algorithm names (by time this document was written) are:
: #sha1WithRSAEncryption, #sha224WithRSAEncryption, #sha256WithRSAEncryption,
: #md2WithRSAEncryption, #md5WithRSAEncryption, #sha384WithRSAEncryption,
: #sha512WithRSAEncryption.

Be aware that most of them are considered insecure nowadays - they are only to be used to support older protocols. If in doubt, ask your security staff.
=== Signing ===
To sign a new certificate, given a root CA certificate:

rootCA signCertificate:cert.

=== Validation ===

''** more to be documented **''

= Key Exchange =
''** to be documented **''

= SSL Streams =
''** to be documented **''

Aktuelle Version vom 2. April 2025, 00:15 Uhr

Reference: MD5Stream inherits from: HashStream

Back to Useful API Functions

Hashing[Bearbeiten]

All hash algorithms are accessed the same way, by either sending one of the convenient utility messages to a hash-stream-class, or by instantiating a hash stream and sending it the data to be hashed (byte-wise or block-wise).

The utility messages are easier to use, but require the hhash data to be already present in a byte- or character collection (i.e. in memory), which may be inefficient or impossible, if big chunks are to be hashed.

The instance messages allow for streams of unknown length to be hashed, to preinitialize the parameters and to fetch/reset the hash value during the operation.

Available hash classes are (among many others): MD5Stream, SHA1Stream, SHA256Stream, SHA512Stream, RipeMD160Stream, SipHashStream, WhirlpoolStream etc.

Open a class browser or evaluate "HashStream allSubclasses inspect" to see them all.
eXept may provide additional hash classes upon request.

Class-Side Utility Protocol[Bearbeiten]

HashStreamClass hashValueOf: aStringOrByteArray
Returns the hash value as a byte vector (the length of the vector depends on the algorithm).
Example:
MD5Stream hashValueOf: 'hello world'
   => #[94 182 59 187 224 30 238 208 147 203 34 187 143 90 205 195]

SHA1Stream hashValueOf: 'hello world'
   => #[42 174 108 53 201 79 207 180 21 219 233 95 64 139 156 233 30 232 70 237]

SHA256Stream hashValueOf: 'hello world'
   => #[185 77 39 185 147 77 62 8 165 46 82 215 218 125 171 250 196 
        132 239 227 122 83 128 238 144 136 247 172 226 239 205 233]
HashStreamClass hashValueHexString: aStringOrByteArray
Returns the hash value as a hex string.
Example:
MD5Stream hashValueHexString: 'hello world'
   => '5eb63bbbe01eeed093cb22bb8f5acdc3'

SHA1Stream hashValueHexString: 'hello world'
   => '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'

SHA256Stream hashValueHexString: 'hello world'
   => 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'
HashStreamClass hashValueOfFile: aFilename
Returns the hash of a file's contents.
Example:
MD5Stream hashValueOfFile: 'Makefile'
SHA256Stream hashValueOfFile: 'Makefile'
(SHA256Stream hashValueOfFile: 'Makefile') hexPrintString
(SHA256Stream hashValueOfFile: 'Makefile') hexPrintString asLowercase

Instance Protocol[Bearbeiten]

More fine control is available by instantiating a hash-stream and sending it the data. First, create an instance:

myHashStream := HashStreamClass new.

then send it the bytes to be hashed with the usual stream messages:

myHashStream nextPutAll: stringOrByteCollection
myHashStream nextPut: characterOrSingleByteValue

and finally ask the stream for its current (running) hashValue with:

myHashStream hashValue

Thus, the above utility in the MD5Stream is equivalent to:

myStream := MD5Stream new.
myStream nextPutAll:'hello world'.
hashBytes := myStream hashValue.
hashHexString := myStream hashValue hexPrintString asLowercase.

Encryption & Decryption[Bearbeiten]

This is done by instantiating a cipher, defining the block-chaining mode and streaming data blocks to it. The way to setup the cipher may differ between the individual algorithms: some require a key only, others require more parameters (e.g. an init vector).

Notice that the raw cipher instance operates in ecb mode, which is very insecure. Send one of the mode messages to define the block chaining mode (ofb, cfg, ctr, etc.)

Common Cipher Class Protocol[Bearbeiten]

All Cipher classes can be asked for the keySize and blockSize:

aCipherClass keySize
the length of the key (in bytes). If it supports multiple keySizes, the preferred or typical size is returned.
aCipherClass keySizes
a collection of supported key sizes. If the cipher supports only one keySize, the collection will contain only one element.
aCipherClass blockSize
blocks of data are encrypted/decrypted in multiples of the blockSize.
Depending on the block chaining mode, data may have to be passed to the cipher in multiples of that size.
aCipherClass blockSizes
a collection of supported block sizes.

Common BlockCipher Instance Protocol[Bearbeiten]

aCipher ofb
returns an object which implements the output feedback mode on top of the cipher. ::Supports the same stream protocol as the cipher. The message length is not required to be a multiple of the cipher's block size.
aCipher ctr
similar for counter mode. The message length is not required to be a multiple of the cipher's block size.
aCipher cbc
similar for cipher block chaining mode. The message length must be a multiple of the cipher's block size.
aCipher cfb
similar for cipher feedback mode. The message length is not required to be a multiple of the cipher's block size.

DES Cipher[Bearbeiten]

In basic ECB mode (attention: insecure!!):

key := #[12 34 56 78 90 12 34 56].
cipher := DesCipher new. 
cipher key: key.
encrypted := cipher encrypt: 'hello world'.
...
decrypted := cipher decrypt: encrypted.

in CFB mode:

key := #[12 34 56 78 90 12 34 56].
cipher := DesCipher new cfb. 
cipher key: key.
encrypted := cipher encrypt: 'hello world'.
...
decrypted := cipher decrypt: encrypted.

Tea Cipher[Bearbeiten]

In basic ECB mode (attention: insecure!):

key := '00112233445566778899aabbccddeeff'.
cipher := TeaCipher new.
cipher key: key.
encrypted := cipher encrypt: 'hello world'.
...
decrypted := cipher decrypt: encrypted.

In OFB (output feedback block mode) mode:

...
cipher := TeaCipher new ofb.
cipher key: key.
cipher initialVector:#[1 2 3 4 5 6 7 8].
...

Others...[Bearbeiten]

Many more ciphers are available; open a browser or evaluate "Cipher allSubclasses inspect" in a workspace.

Certificate Handling[Bearbeiten]

Reading from a PEM File[Bearbeiten]

Use fromPemStream: to convert a PEM file.

cert := X509Certificate fromPemStream:('file.pem' asFilename readStream)

This method can also read a string in case the PEM is already available:

cert := X509Certificate fromPemStream:'
-----BEGIN CERTIFICATE-----
MIIHBTCCBO2gAwIBAgIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJERTEa
MBgGA1UEChMRRXhlcHQgU29mdHdhcmUgQUcxEDAOBgNVBAsTB1Rlc3RpbmcxFzAV
...
vthHg54SuEay1ge+PvggvOqvMB4laWakbA==
-----END CERTIFICATE-----
'.

Writing as a PEM File[Bearbeiten]

'filename.pem' asFilename writeStream
   nextPutAll:cert asSignedPemString;
   close.

Writing as a DER Encoded File[Bearbeiten]

 'filename.crt' asFilename writeStream
      binary;
      nextPutAll:caCert asSignedDerBytes;
      close.

or more convenient:

 'filename.crt' asFilename contents:(caCert asSignedDerBytes)

Creation[Bearbeiten]

To create a self-signed certificate,

cert := X509CaCertificate new
       subjectNameString:'C=DE, O=MyCompany, CN=Test';
       issuerNameString:'C=DE, O= MyCompany, CN=Test-CA';
       serialNumber:4711;
       signatureAlgorithmNameString:#sha256WithRSAEncryption;
       startValidity:Timestamp now;
       endValidity:(Date today + 365) asTimestamp;
       key:(RSASecretCryptKey 
                 generateKeyLength:4096 
                 publicExponent:65537 
                 rng:RandomGenerator new);
       signSelf

Supported algorithm names (by time this document was written) are:

#sha1WithRSAEncryption, #sha224WithRSAEncryption, #sha256WithRSAEncryption,
#md2WithRSAEncryption, #md5WithRSAEncryption, #sha384WithRSAEncryption,
#sha512WithRSAEncryption.

Be aware that most of them are considered insecure nowadays - they are only to be used to support older protocols. If in doubt, ask your security staff.

Signing[Bearbeiten]

To sign a new certificate, given a root CA certificate:

rootCA signCertificate:cert.

Validation[Bearbeiten]

** more to be documented **

Key Exchange[Bearbeiten]

** to be documented **

SSL Streams[Bearbeiten]

** to be documented **



Copyright © 2014-2024 eXept Software AG