diff options
author | Stefan Hornburg (Racke) <racke@linuxia.de> | 2016-09-17 17:20:15 +0200 |
---|---|---|
committer | Stefan Hornburg (Racke) <racke@linuxia.de> | 2016-09-17 17:20:15 +0200 |
commit | f064ae60367c773a9a4a5dff8dec904c88274216 (patch) | |
tree | f6f37ec6d8e6ccbf3031fb89bdfa33660172ed3e |
Import ciphersaber_1.01.orig.tar.gz
[dgit import orig ciphersaber_1.01.orig.tar.gz]
-rw-r--r-- | Build.PL | 23 | ||||
-rw-r--r-- | Changes | 37 | ||||
-rw-r--r-- | MANIFEST | 17 | ||||
-rw-r--r-- | META.json | 47 | ||||
-rw-r--r-- | META.yml | 25 | ||||
-rw-r--r-- | Makefile.PL | 16 | ||||
-rw-r--r-- | README | 34 | ||||
-rw-r--r-- | lib/Crypt/CipherSaber.pm | 275 | ||||
-rw-r--r-- | t/CS2.t | 19 | ||||
-rw-r--r-- | t/base.t | 36 | ||||
-rw-r--r-- | t/bigfile.t | 25 | ||||
-rw-r--r-- | t/both_long.t | 20 | ||||
-rw-r--r-- | t/create.t | 16 | ||||
-rw-r--r-- | t/encrypt.t | 32 | ||||
-rw-r--r-- | t/fh_encrypt.t | 120 | ||||
-rw-r--r-- | t/smiles.cs1 | bin | 0 -> 1423 bytes | |||
-rw-r--r-- | t/smiles.png | bin | 0 -> 1413 bytes |
17 files changed, 742 insertions, 0 deletions
diff --git a/Build.PL b/Build.PL new file mode 100644 index 0000000..0002cdd --- /dev/null +++ b/Build.PL @@ -0,0 +1,23 @@ +use strict; +use warnings; +use Module::Build; + +my $builder = Module::Build->new( + module_name => 'Crypt::CipherSaber', + license => 'perl', + dist_author => 'chromatic <chromatic@cpan.org>', + dist_version_from => 'lib/Crypt/CipherSaber.pm', + requires => + { + 'Scalar::Util' => '1.004002', + }, + build_requires => + { + 'Test::Simple' => '0.60', + 'Test::Warn' => '0.30', + }, + add_to_cleanup => [ 'Crypt-CipherSaber-*' ], + create_makefile_pl => 'traditional', +); + +$builder->create_build_script(); @@ -0,0 +1,37 @@ +Revision history for Perl extension Crypt::CipherSaber. + +1.00 Tue Jul 12 23:45:00 UTC 2005 + - migrated to Build.PL + - added POD, POD coverage, and signature tests + - generated traditional Makefile.PL + - bumped up version number + - ported tests to Test::Simple + - bumped up test coverage + - updated README + +0.61 Sat May 25 17:31:52 UTC 2002 + - avoid uninitialized value warnings in fh_crypt() + + Thu May 10 2001 + - fixed _gen_iv() to generate 255 characters (thanks to John Wiersba) + + Sun Apr 29 2001 + - added license/copyright information to the pod in the module itself + +0.60 Sat Apr 7 2001 + - some internal cleanup + - added some comments + - added documentation for fh_crypt() + + Thu Apr 5 2001 + - made _gen_iv() work with Perl 5.004 (again Sympa) + - added fh_crypt() + - added _do_crypt() to help with fh_crypt() + - made crypt() use _do_crypt() + - added t/bigfile.t and t/fh_encrypt.t + +0.51 Wed Apr 4 2001 UNRELEASED VERSION + - made decrypt() work with Perl 5.004 (for Sympa project) + +0.50 Fri Dec 1 17:02:02 2000 + - original version; created by h2xs 1.19 diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..e890589 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,17 @@ +Build.PL +Changes +lib/Crypt/CipherSaber.pm +Makefile.PL +MANIFEST +META.yml +README +t/CS2.t +t/base.t +t/bigfile.t +t/both_long.t +t/create.t +t/encrypt.t +t/fh_encrypt.t +t/smiles.cs1 +t/smiles.png +META.json diff --git a/META.json b/META.json new file mode 100644 index 0000000..71ccf9e --- /dev/null +++ b/META.json @@ -0,0 +1,47 @@ +{ + "abstract" : "Perl module implementing CipherSaber encryption.", + "author" : [ + "chromatic <chromatic@cpan.org>" + ], + "dynamic_config" : 1, + "generated_by" : "Module::Build version 0.4211", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "Crypt-CipherSaber", + "prereqs" : { + "build" : { + "requires" : { + "Test::Simple" : "0.60", + "Test::Warn" : "0.30" + } + }, + "configure" : { + "requires" : { + "Module::Build" : "0.42" + } + }, + "runtime" : { + "requires" : { + "Scalar::Util" : "1.004002" + } + } + }, + "provides" : { + "Crypt::CipherSaber" : { + "file" : "lib/Crypt/CipherSaber.pm", + "version" : "1.01" + } + }, + "release_status" : "stable", + "resources" : { + "license" : [ + "http://dev.perl.org/licenses/" + ] + }, + "version" : "1.01" +} diff --git a/META.yml b/META.yml new file mode 100644 index 0000000..932da12 --- /dev/null +++ b/META.yml @@ -0,0 +1,25 @@ +--- +abstract: 'Perl module implementing CipherSaber encryption.' +author: + - 'chromatic <chromatic@cpan.org>' +build_requires: + Test::Simple: '0.60' + Test::Warn: '0.30' +configure_requires: + Module::Build: '0.42' +dynamic_config: 1 +generated_by: 'Module::Build version 0.4211, CPAN::Meta::Converter version 2.150001' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: '1.4' +name: Crypt-CipherSaber +provides: + Crypt::CipherSaber: + file: lib/Crypt/CipherSaber.pm + version: '1.01' +requires: + Scalar::Util: '1.004002' +resources: + license: http://dev.perl.org/licenses/ +version: '1.01' diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..6460abd --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,16 @@ +# Note: this file was auto-generated by Module::Build::Compat version 0.4211 +use ExtUtils::MakeMaker; +WriteMakefile +( + 'NAME' => 'Crypt::CipherSaber', + 'VERSION_FROM' => 'lib/Crypt/CipherSaber.pm', + 'PREREQ_PM' => { + 'Scalar::Util' => '1.004002', + 'Test::Simple' => '0.60', + 'Test::Warn' => '0.30' + }, + 'INSTALLDIRS' => 'site', + 'EXE_FILES' => [], + 'PL_FILES' => {} +) +; @@ -0,0 +1,34 @@ +Crypt::CipherSaber +------------------ + +version 1.00 Wed Jul 13 01:37:53 UTC 2005 + +Crypt::CipherSaber is a Perl module providing an object oriented interface to +CipherSaber-1 and CipherSaber-2 encryption. See the POD for further details on +use. See http://ciphersaber.gurus.com for more information about CipherSaber. + +After unpacking the tarball, to install this module type: + + $ perl Build.PL + $ ./Build + $ ./Build test + # ./Build install + +You can also use the Makefile.PL, but I don't. + +The encryption itself is simple, relatively fast, and fairly secure. It uses a +shared secret system, and is suitable even for binary files. It should run +without modification anywhere Perl runs. This ought to work as far back as +Perl 5.004, so please let me know how it does. + +Prerequisites: Scalar::Util +Test requirements: Test::More, Test::Warn + +Potential enhancements and plans: + + * built-in support for a better randomization scheme? + * support changing keys in an object rather than creating a new one? + +Copyright (c) 2001, 2005 chromatic (chromatic at wgz dot org), all rights +reserved. This program is free software; you can use, modify, and redistribute +it under the same terms as Perl 5.8.x itself. diff --git a/lib/Crypt/CipherSaber.pm b/lib/Crypt/CipherSaber.pm new file mode 100644 index 0000000..7cb7cc0 --- /dev/null +++ b/lib/Crypt/CipherSaber.pm @@ -0,0 +1,275 @@ +package Crypt::CipherSaber; + +use strict; + +use Carp; +use Scalar::Util 'reftype'; + +use vars '$VERSION'; + +$VERSION = '1.01'; + +sub new +{ + my ($class, $key, $N) = @_; + + # CS-2 shuffles the state array N times, CS-1 once + if ( !( defined $N ) or ( $N < 1 ) ) + { + $N = 1; + } + bless [ $key, [ 0 .. 255 ], $N ], $class; +} + +sub crypt +{ + my ($self, $iv, $message) = @_; + $self->_setup_key($iv); + + my $state = $self->[1]; + my $output = _do_crypt( $state, $message ); + $self->[1] = [ 0 .. 255 ]; + return $output; +} + +sub encrypt +{ + my $self = shift; + my $iv = $self->_gen_iv(); + return $iv . $self->crypt( $iv, @_ ); +} + +sub decrypt +{ + my $self = shift; + my ( $iv, $message ) = unpack( "a10a*", +shift ); + return $self->crypt( $iv, $message ); +} + +sub fh_crypt +{ + my ( $self, $in, $out, $iv ) = @_; + + for my $glob ($in, $out) + { + my $reftype = reftype( $glob ) || ''; + unless ($reftype eq 'GLOB') + { + require Carp; + Carp::carp( 'Non-filehandle passed to fh_crypt()' ); + return; + } + } + + local *OUT = $out; + if ( defined($iv) ) + { + $iv = $self->_gen_iv() if length($iv) == 1; + $self->_setup_key($iv); + print OUT $iv; + } + + my $state = $self->[1]; + + my ( $buf, @vars ); + + while (<$in>) + { + unless ($iv) + { + ( $iv, $_ ) = unpack( "a10a*", $_ ); + $self->_setup_key($iv); + } + my $line; + ( $line, $state, @vars ) = _do_crypt( $state, $_, @vars ); + print OUT $line; + } + $self->[1] = [ 0 .. 255 ]; + return 1; +} + +################### +# +# PRIVATE METHODS +# +################### +sub _gen_iv +{ + my $iv; + for ( 1 .. 10 ) + { + $iv .= chr( int( rand(256) ) ); + } + return $iv; +} + +sub _setup_key +{ + my $self = shift; + my $key = $self->[0] . shift; + my @key = map { ord } split( //, $key ); + my $state = $self->[1]; + my $j = 0; + my $length = @key; + + # repeat N times, for CS-2 + for ( 1 .. $self->[2] ) + { + for my $i ( 0 .. 255 ) + { + $j += ( $state->[$i] + ( $key[ $i % $length ] ) ); + $j %= 256; + ( @$state[ $i, $j ] ) = ( @$state[ $j, $i ] ); + } + } +} + +sub _do_crypt +{ + my ( $state, $message, $i, $j, $n ) = @_; + + my $output = ''; + + for ( 0 .. ( length($message) - 1 ) ) + { + $i++; + $i %= 256; + $j += $state->[$i]; + $j %= 256; + @$state[ $i, $j ] = @$state[ $j, $i ]; + $n = $state->[$i] + $state->[$j]; + $n %= 256; + $output .= chr( $state->[$n] ^ ord( substr( $message, $_, 1 ) ) ); + } + + return wantarray ? ( $output, $state, $i, $j, $n ) : $output; +} + +1; + +__END__ + +=head1 NAME + +Crypt::CipherSaber - Perl module implementing CipherSaber encryption. + +=head1 SYNOPSIS + + use Crypt::CipherSaber; + my $cs = Crypt::CipherSaber->new('my sad secret key'); + + my $coded = $cs->encrypt('Here is a secret message for you'); + my $decoded = $cs->decrypt($coded); + + # encrypt from and to a file + open my $in, 'secretletter.txt' or die "Can't open infile: $!"; + open my $out, '>', 'secretletter.cs1' or die "Can't open outfile: $!"; + binmode $in; + binmode $out; + + $cs->fh_crypt($in, $out, 1); + + # decrypt from and to a file + open my $in, 'secretletter.txt' or die "Can't open infile: $!"; + open my $out, '>', 'secretletter.cs1' or die "Can't open outfile: $!"; + + binmode $in; + binmode $out; + $cs->fh_crypt($in, $out); + +=head1 DESCRIPTION + +The Crypt::CipherSaber module implements CipherSaber encryption, described at +L<http://ciphersaber.gurus.com/>. It is simple, fairly speedy, and relatively +secure algorithm based on RC4. I<Relatively>, given RC4. + +Encryption and decryption are done based on a secret key, which must be shared +with all intended recipients of a message. + +=head1 METHODS + +=over + +=item B<new($key, $N)> + +Initialize a new Crypt::CipherSaber object. C<$key> is a required parameter: +the key used to encrypt or to decrypt messages. C<$N> is optional. If +provided and greater than one, it causes the object to use CipherSaber-2 +encryption (slightly slower but more secure). If not specified, or equal to 1, +the module defaults to CipherSaber-1 encryption. C<$N> must be a positive +integer greater than one. + +=item B<encrypt($message)> + +Encrypt a message. This uses the key stored in the current Crypt::CipherSaber +object. It generates a 10-byte random IV (Initialization Vector) +automatically, as defined in the RC4 specification. This returns a string +containing the encrypted message. + +Note that the encrypted message may contain unprintable characters, as it uses +the extended ASCII character set (valid numbers 0 through 255). + +=item B<decrypt($message)> + +Decrypt a message. For the curious, the first ten bytes of an encrypted +message are the IV, so this must strip it off first. This returns a string +containing the decrypted message. + +The decrypted message may also contain unprintable characters, as the +CipherSaber encryption scheme handles binary filesIf this is important to you, +be sure to treat the results correctly. + +=item B<crypt($iv, $message)> + +If you wish to generate the IV with a more cryptographically secure random +string (at least compared to Perl's builtin C<rand()> operator), you may do so +separately, passing it to this method directly. The IV must be a ten-byte +string consisting of characters from the extended ASCII set. + +This is generally only useful for encryption, although you may extract the +first ten characters of an encrypted message and pass them in yourself. You +might as well call B<decrypt()>, though. The more random the IV, the stronger +the encryption tends to be. On some operating systems, you can read from +F</dev/random>. Other approaches are the L<Math::TrulyRandom> module, or +compressing a file, removing the headers, and compressing it again. + +=item B<fh_crypt( $in_fh, $out_fh, ($iv))> + +For the sake of efficiency, Crypt::CipherSaber can operate on filehandles. +It's not super brilliant, but it's relatively fast and sane. If your platform +needs to use C<binmode()>, this is your responsibility. It is also your +responsibility to close the files. + +You may also pass in an optional third parameter, an IV. There are three +possibilities here. If you pass no IV, C<fh_crypt()> will pull the first ten +bytes from the input filehandle and use that as an IV. This corresponds to +decryption. If you pass in an IV of your own, it will use that when encrypting +the file. If you pass in the value C<1>, it will generate a new, random IV for +you. This corresponds to an encryption. + +=back + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2000 - 2015 chromatic + +This library is free software; you can use, modify, and redistribute it under +the same terms as Perl 5.20.x itself. + +=head1 AUTHOR + +chromatic C<< chromatic at cpan dot org >> + +thanks to jlp for testing, moral support, and never fearing the icky details +and to the fine folks at PerlMonks L<http://perlmonks.org/>. + +Additional thanks to Olivier Salaun and the Sympa project +L<http://www.sympa.org> for testing. + +=head1 SEE ALSO + +the CipherSaber home page at L<http://ciphersaber.gurus.com/> + +perl(1), rand(). + +=cut @@ -0,0 +1,19 @@ +#!perl -w + +# now do a bidirectional check with CS-2 + +BEGIN +{ + chdir 't' if -d 't'; +} + +use strict; +use Test::More tests => 2; + +use_ok('Crypt::CipherSaber'); + +my $cs2 = Crypt::CipherSaber->new( 'second key', 5 ); +my $long_line = join( ' ', ( 1 .. 100 ) ); +my $coded = $cs2->encrypt($long_line); +is( $cs2->decrypt($coded), $long_line, + 'CS-2 should work on texts longer than IV' ); diff --git a/t/base.t b/t/base.t new file mode 100644 index 0000000..a1ff1fd --- /dev/null +++ b/t/base.t @@ -0,0 +1,36 @@ +#!perl -w + +BEGIN +{ + chdir 't' if -d 't'; +} + +use strict; + +use Test::More 'no_plan'; # tests => 2; +use Test::Warn; + +my $module = 'Crypt::CipherSaber'; +use_ok( $module ); + +# first, try to create an object +my $cs = $module->new('first key'); +isa_ok( $cs, $module ); +is( $cs->[2], 1, 'new() should default to an N of 1 with none given' ); + +$cs = $module->new('first key', 0); +is( $cs->[2], 1, '... or one given < 1' ); + +can_ok( $cs, 'crypt' ); +can_ok( $cs, 'encrypt' ); +can_ok( $cs, 'decrypt' ); + +can_ok( $cs, 'fh_crypt' ); +my $result; +warning_like { $result = $cs->fh_crypt() } qr/Non-filehandle/, + 'fh_crypt() should warn without a valid input filehandle'; +is( $result, undef, '... returning nothing' ); + +warning_like { $result = $cs->fh_crypt( \*STDIN ) } qr/Non-filehandle/, + '... and should warn without a valid output filehandle'; +is( $result, undef, '... also returning nothing' ); diff --git a/t/bigfile.t b/t/bigfile.t new file mode 100644 index 0000000..04c74f2 --- /dev/null +++ b/t/bigfile.t @@ -0,0 +1,25 @@ +#!perl -w + +BEGIN +{ + chdir 't' if -d 't'; +} + +use strict; +use Test::More tests => 2; + +use_ok( 'Crypt::CipherSaber' ); + +my $cs = Crypt::CipherSaber->new( 'sdrawkcabsihtdaeR' ); +open( INPUT, 'smiles.cs1' ) or die "Couldn't open: $!"; +binmode(INPUT); +open(OUTPUT, '> smiles.png') or die "Couldn't open: $!"; +binmode(OUTPUT); +$cs->fh_crypt(\*INPUT, \*OUTPUT); +close INPUT; +close OUTPUT; + +open(TEST, 'smiles.png') or die "Couldn't open: $!"; +my $line = <TEST>; + +like( $line, qr/PNG/, 'Encrypting a large file should not mangle it' ); diff --git a/t/both_long.t b/t/both_long.t new file mode 100644 index 0000000..8055692 --- /dev/null +++ b/t/both_long.t @@ -0,0 +1,20 @@ +#!perl -w + +# encrypt and decrypt a line greater than 256 characters long +# this tests for a subtle bug, ie, missing a modulo on $i + +BEGIN +{ + chdir 't' if -d 't'; +} + +use strict; + +use Test::More tests => 2; + +use_ok('Crypt::CipherSaber'); + +my $cs = Crypt::CipherSaber->new( 'first key' ); +my $long_line = join( ' ', ( 1 .. 100 ) ); +my $coded = $cs->encrypt($long_line); +is( $cs->decrypt( $coded ), $long_line, 'round-tripping should work' ); diff --git a/t/create.t b/t/create.t new file mode 100644 index 0000000..013b4ff --- /dev/null +++ b/t/create.t @@ -0,0 +1,16 @@ +#!perl -w + +BEGIN +{ + chdir 't' if -d 't'; +} + +use strict; +use Test::More tests => 2; + +my $module = 'Crypt::CipherSaber'; +use_ok( $module ); + +# first, try to create an object +my $cs = $module->new('first key'); +isa_ok( $cs, $module ); diff --git a/t/encrypt.t b/t/encrypt.t new file mode 100644 index 0000000..6b5e442 --- /dev/null +++ b/t/encrypt.t @@ -0,0 +1,32 @@ +#!perl -w + +BEGIN +{ + chdir 't' if -d 't'; +} + +use strict; + +use Test::More tests => 3; +use_ok( 'Crypt::CipherSaber' ); + +# encrypt a message +my $cs = Crypt::CipherSaber->new( 'asdfg' ); +my $coded = $cs->crypt( 'abcdefghij', 'This is another test.' ); +my $message = join( '', + map { chr } + qw ( 153 90 51 37 126 114 217 0 50 245 103 36 219 18 4 44 169 53 32 64 15 ) +); + +is( $coded, $message, 'encryption of known text should produce known output' ); + +# decrypt a previously encrypted message +$message = join( '', + map { chr } + qw( 99 228 225 111 163 246 142 168 143 125 239 199 167 58 192 81 211 122 19 + 200 97 57 101 151 19 + ) +); + +is( $cs->decrypt($message), 'This is a test.', + '... and decryption should produce known output' ); diff --git a/t/fh_encrypt.t b/t/fh_encrypt.t new file mode 100644 index 0000000..35a74fb --- /dev/null +++ b/t/fh_encrypt.t @@ -0,0 +1,120 @@ +#!perl -w + +BEGIN +{ + chdir 't' if -d 't'; +} + +use strict; +use Test::More tests => 6; +use_ok( 'Crypt::CipherSaber' ); + +# tests the fh_crypt() method +# this will fail if the state array is not reinitialized ... oops! +use Crypt::CipherSaber; +use File::Spec; + +open( IN, 'smiles.cs1' ) or die "Can't get IV!\n"; +binmode(IN); +my $iv = unpack( "a10", <IN> ); + +# encrypt a message +my $cs = Crypt::CipherSaber->new( 'sdrawkcabsihtdaeR' ); +open( IN, 'smiles.png' ) or die "Can't open input file!\n"; +open( OUT, '> outsmiles.cs1' ) or die "Can't open output file!\n"; +binmode(IN); +binmode(OUT); + +ok( $cs->fh_crypt( \*IN, \*OUT, $iv ), + 'fh_crypt() should return true if everything works' ); + +open( ENCRYPTED, 'outsmiles.cs1' ) or die "Can't open encrypted file!\n"; +open( FIXED, 'smiles.cs1' ) or die "Can't open fixed file!\n"; +binmode(ENCRYPTED); +binmode(FIXED); + +my $status = 0; +while (<ENCRYPTED>) +{ + my $fixed = <FIXED>; + my $pos = 0; + for my $char ( split( //, $_ ) ) + { + next if ( substr( $fixed, $pos++, 1 ) eq $char ); + $status = 1; + } + last if $status; +} + +ok( ! $status, + 'There should be no characters in common between input and output' ); + +open( IN, 'smiles.cs1' ) or die "Can't open input file 2!\n"; +open( OUT, '> outsmiles.png' ) or die "Can't open output file 2!\n"; +binmode(IN); +binmode(OUT); + +ok( $cs->fh_crypt( \*IN, \*OUT ), + 'fh_crypt() should return true if everything works (decrypting)' ); + +close(IN); +close(OUT); + +open( ENCRYPTED, 'outsmiles.png' ) or die "Can't open encrypted file!\n"; +open( FIXED, 'smiles.png' ) or die "Can't open fixed file!\n"; +binmode(ENCRYPTED); +binmode(FIXED); + +$status = 0; +while (<ENCRYPTED>) +{ + my $fixed = <FIXED>; + unless ($_ eq $fixed) + { + $status = 1; + last; + } +} + +close(ENCRYPTED); +close(FIXED); + +ok( ! $status, '... with no characters in common' ); +open( IN, 'smiles.png' ) or die "Cannot read smiles.png: $!"; +open( OUT, '> smiles_2.cs1' ) or die "Cannot write to smiles_2.cs1: $!"; +binmode( IN ); +binmode( OUT ); +$cs->fh_crypt( \*IN, \*OUT, 1 ); +close IN; +close OUT; + +open( IN, 'smiles_2.cs1' ) or die "Cannot read smiles_2.cs1: $!"; +open( OUT, '> smiles_2.png' ) or die "Cannot write to smiles_2.png $!"; +binmode( IN ); +binmode( OUT ); +$cs->fh_crypt( \*IN, \*OUT ); +close IN; +close OUT; + +open( SOURCE, 'smiles.png' ) or die "Cannot read smiles.png: $!"; +open( DEST, 'smiles_2.png' ) or die "Cannot read smiles_2.png: $!"; + +binmode SOURCE; +binmode DEST; + +$status = 0; +while (<SOURCE>) +{ + unless ($_ eq <DEST>) + { + $status = 1; + last; + } +} + +ok( ! $status, 'autogenerating and autoreading IV should also round-trip' ); + +END +{ + 1 while unlink qw( smiles_2.cs1 smiles_2.png outsmiles.cs1 outsmiles.png ); +} diff --git a/t/smiles.cs1 b/t/smiles.cs1 Binary files differnew file mode 100644 index 0000000..135aa76 --- /dev/null +++ b/t/smiles.cs1 diff --git a/t/smiles.png b/t/smiles.png Binary files differnew file mode 100644 index 0000000..3962d32 --- /dev/null +++ b/t/smiles.png |