Cipher.pm - Perl 6 Cipher API
class Cipher::Not is Cipher { method zeroize() { # No state to zeroize } method _cipher(byte @data) { return map { +^$_ }, @data; } } #Later... my $encrypt = Cipher::Not.new(:mode<encrypt>); print $encrypt.cipher($_) for =$IN; # Works with bytearrays and strings print $encrypt.finishstr();
The Cipher API is a common interface for cryptographic ciphers. Ciphers conforming to the Cipher API are interchangable, allowing a programmer to change ciphers simply by changing the class name used.
Ciphers used with the Cipher API must operate on bytes or multi-byte blocks; the API does not support enciphering individual bits. Also note that the Cipher API operates at the byte level, not the character level, so different character encodings may be enciphered in different ways.
The Cipher API has functional, procedural, and object-oriented interfaces. The functional and object-oriented interfaces both follow the same basic steps, albeit with different interfaces:
The procedural interface does the same thing within a single call, hiding the full complexity.
The Cipher API's procedural interface is good enough for many purposes. Although the interface is said to be procedural, it is invoked via two class methods.
encipher
$ciphertext = Some::Cipher.encipher($plaintext, :opt<value>, :opt2<value2>);
Enciphers the plaintext string, returning the ciphertext version. Most algorithms will have a key, which will be specified in the options; check your cipher's documentation for details.
decipher
$plaintext = Some::Cipher.decipher($ciphertext, :opt<value>, :opt2<value2>);
Does the same, but deciphers instead of enciphering. (There may not be a distinction for some ciphers.)
The Cipher API's functional interface is perhaps the easiest one that allows for continuous ciphering.
Both of these functions return a closure. Call the closure with a block of data to have it enciphered or deciphered; when you're done, call the closure with no arguments to finish the ciphering and clear the cipher's state. Remember that ciphering steps may not return all (or any) of the data you passed in, and that the finishing step may return data.
An example:
&cipher := Cipher::Arcfour.encipherer(:key($key)); #Create the cipher closure print cipher($text1); # Encrypt some data print cipher($text2); # Encrypt more data print cipher(); # Finish up
encipherer
$encipher = Some::Cipher.encipherer(:opt1<value1>, :opt2<value2>);
Create an encipherer closure, which can be called repeatedly to encipher data. The encipherer closure can be called with a string, and should be called at the end of enciphering with zero arguments.
decipherer
$decipher = Some::Cipher.decipherer(:opt1<value1>, :opt2<value2>);
The same, except that the closure deciphers instead of enciphering.
The Cipher API is fundamentally object-oriented; the procedural and functional interfaces are layers on top of the object-oriented backend.
To use the Cipher API, you must first create an object of the appropriate class, passing the key, a mode (either "enciphering" or "deciphering"), and any other options to the constructor. Then you call the cipher() method repeatedly with your data. Finally, call the finish() method to return any leftover data and clear the cipher object.
The methods intended to be used by Cipher API users are:
new
$cipher_obj = Some::Cipher.new(:opt1<value1>, :opt2<value2>, :mode<enciphering>);
This class method constructs a new cipher object. The options passed to the new constructor generally include some sort of key, and sometimes also parameters for block size and so on; see the cipher module's documentation for details. The mode value indicates the operation to be performed; the values encrypting, encrypt and encipher are equivalent to enciphering, while decrypting, decrypt and decipher are equivalent to deciphering.
mode
encrypting
encrypt
enciphering
decrypting
decrypt
deciphering
cipher
push @output, $cipher_obj.cipher($data);
Enciphers or deciphers the given data. May return data which is part of the ciphertext, but is not necessarily the ciphertext version of the data given. The data may be either a string or an array of bytes; the array of bytes will be slightly faster.
finish
push @output, $cipher_obj.finish();
Completes ciphering of any leftover data and returns it as an array of bytes, then clears the object's internal state. This should be called as the last step of enciphering.
finishstr
push @output, $cipher_obj.finishstr();
The same as finish, but returns the data as a string instead of an array of bytes.
zeroize
$cipher_obj.zeroize();
Tells the cipher object to clear its internal state as completely as possible. This is automatically done as part of finish, finishstr and the destructor, but there may be situations in which explicitly zeroizing the cipher object would be desirable.
Note that calling any methods on a zeroed (and hence, also a finished) cipher object has undefined results.
Although the API seems large, most of it is implemented within the Cipher class itself; in fact, the only method that truly must be implemented is the one that actually enciphers the data. They may choose, however, to override any method for speed--although they should be careful to avoid changing the actual semantics.
Cipher
Please note that most of the time, it will not be necessary to write these methods yourself; in particular, Cipher::Block and Cipher::Stream can reduce the implementation of most block and stream ciphers to a constructor, the cryptographic core, and a couple attributes.
BEGIN
Although not technically part of the API, most ciphers will want to implement a constructor with BEGIN.
_cipher
C<method _cipher(Array of byte $data) returns Array of byte {...}>
Performs the actual ciphering. This method should operate on a copy of the data, either by declaring $data to be an is copy variable or by making a copy internally, and should return the copy once it has been encrypted or decrypted.
$data
is copy
_head
C<method _head() returns Array of byte {...}>
Returns any data the cipher needs to add at the beginning, before the ciphertext. This will be prepended to the return value of the first call to _cipher. This is rarely used by the cipher itself; more often it is used by a block cipher mode role to add some information to the output.
A default implementation of this method is provided which returns nothing.
_tail
C<method _tail() returns Array of byte {...}>
Called as part of finish; ciphers and returns any pending data. Block ciphers should buffer input data until they have an entire block, then cipher the block and return the new ciphertext (or plaintext). A call to _tail indicates that there is no more incoming data, and the remaining data should be padded and ciphered. (The Cipher::Block class takes care of much of this.)
C<method zeroize() returns Void {...}>
Clears the cipher object's internal structures.
Cipher authors should assume that if this method is being called, the Secret Police are breaking down the door and Our Heroes need any sensitive data still in the cipher to be deleted immediately. This method should be as thorough as possible; for example, it should not merely set arrays to (), but loop through them setting all the elements to 0. In reality, most calls will be for pedestrian events like object destruction, but let's not make too many assumptions.
()
This code has not been reviewed by a security expert, and may contain bugs and vulnerabilities. Perform your own security analysis before using it in any sensitive application.
The authors and copyright holders DO NOT take responsibility for any insecurity caused by bugs in the Cipher API or individual ciphers.
Cipher::Stream, Cipher::Block
Digest
Bruce Schneier. Applied Cryptography, Second Edition. 1995, published by John Wiley & Sons, Inc.
Copyright (C) 2005 Brent Royal-Gordon <brent@brentdax.com>.
This code is free software, and may be used, distributed and/or modified under the same terms as Perl itself.
5 POD Errors
The following errors were encountered while parsing the POD:
=back doesn't take any parameters, but you said =back 4
To install Perl6::Pugs, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Perl6::Pugs
CPAN shell
perl -MCPAN -e shell install Perl6::Pugs
For more information on module installation, please visit the detailed CPAN module installation guide.