commit 929d5c3bca37f737dc2514564ea51c0a16124211 Author: Tomasz Sowa Date: Sun Jan 8 04:08:02 2012 +0000 initial import of 'tito' library git-svn-id: svn://ttmath.org/publicrep/tito/src@361 e52654a7-88a9-db11-a3e9-0013d4bc506e diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..3035a72 --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +include Makefile.o.dep + + +all: tito.a + +tito.a: $(o) + ar rcs tito.a $(o) + + +%.o: %.cpp + $(CXX) -c $(CXXFLAGS) $< + + + +depend: + makedepend $(CXXFLAGS) -Y. -f- *.cpp > Makefile.dep + echo -n "o = " > Makefile.o.dep + ls -1 *.cpp | xargs -I foo echo -n foo " " | sed -E "s/([^\.]*)\.cpp[ ]/\1\.o/g" >> Makefile.o.dep + + +clean: + rm -f *.o + rm -f *.a + + +include Makefile.dep diff --git a/Makefile.dep b/Makefile.dep new file mode 100755 index 0000000..3e30878 --- /dev/null +++ b/Makefile.dep @@ -0,0 +1,7 @@ +# DO NOT DELETE + +edanticaes.o: aes.h +edanticbase64.o: base64.h +edanticcrypto.o: crypto.h aes.h base64.h /home/tomek/roboczy/ezc/src/utf8.h +edanticcrypto.o: misc.h +edanticmisc.o: misc.h diff --git a/Makefile.o.dep b/Makefile.o.dep new file mode 100755 index 0000000..082a117 --- /dev/null +++ b/Makefile.o.dep @@ -0,0 +1 @@ +o = aes.o base64.o crypto.o misc.o diff --git a/aes.cpp b/aes.cpp new file mode 100755 index 0000000..a1b135d --- /dev/null +++ b/aes.cpp @@ -0,0 +1,1308 @@ +/* + * This file is a part of Tito - a cryptography library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2012, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "aes.h" + + +namespace Tito +{ + + + +AES::uint8 AES::sbox[16][16] = { + { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 }, + { 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 }, + { 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 }, + { 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 }, + { 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 }, + { 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf }, + { 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 }, + { 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 }, + { 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 }, + { 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb }, + { 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 }, + { 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 }, + { 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a }, + { 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e }, + { 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf }, + { 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }}; + + +AES::uint8 AES::invsbox[16][16] = { + { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb }, + { 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb }, + { 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e }, + { 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 }, + { 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 }, + { 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 }, + { 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 }, + { 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b }, + { 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 }, + { 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e }, + { 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b }, + { 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 }, + { 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f }, + { 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef }, + { 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 }, + { 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }}; + + + +int AES::mixcolumntab[4][4] = { + {2, 3, 1, 1}, + {1, 2, 3, 1}, + {1, 1, 2, 3}, + {3, 1, 1, 2}}; + + +int AES::invmixcolumntab[4][4] = { + {14, 11, 13, 9}, + {9, 14, 11, 13}, + {13, 9, 14, 11}, + {11, 13, 9, 14}}; + + + +AES::uint8 AES::Rcon[10] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}; + + + +AES::uint8 AES::gf_mul9[16][16] = { + { 0x00,0x09,0x12,0x1b,0x24,0x2d,0x36,0x3f,0x48,0x41,0x5a,0x53,0x6c,0x65,0x7e,0x77 }, + { 0x90,0x99,0x82,0x8b,0xb4,0xbd,0xa6,0xaf,0xd8,0xd1,0xca,0xc3,0xfc,0xf5,0xee,0xe7 }, + { 0x3b,0x32,0x29,0x20,0x1f,0x16,0x0d,0x04,0x73,0x7a,0x61,0x68,0x57,0x5e,0x45,0x4c }, + { 0xab,0xa2,0xb9,0xb0,0x8f,0x86,0x9d,0x94,0xe3,0xea,0xf1,0xf8,0xc7,0xce,0xd5,0xdc }, + { 0x76,0x7f,0x64,0x6d,0x52,0x5b,0x40,0x49,0x3e,0x37,0x2c,0x25,0x1a,0x13,0x08,0x01 }, + { 0xe6,0xef,0xf4,0xfd,0xc2,0xcb,0xd0,0xd9,0xae,0xa7,0xbc,0xb5,0x8a,0x83,0x98,0x91 }, + { 0x4d,0x44,0x5f,0x56,0x69,0x60,0x7b,0x72,0x05,0x0c,0x17,0x1e,0x21,0x28,0x33,0x3a }, + { 0xdd,0xd4,0xcf,0xc6,0xf9,0xf0,0xeb,0xe2,0x95,0x9c,0x87,0x8e,0xb1,0xb8,0xa3,0xaa }, + { 0xec,0xe5,0xfe,0xf7,0xc8,0xc1,0xda,0xd3,0xa4,0xad,0xb6,0xbf,0x80,0x89,0x92,0x9b }, + { 0x7c,0x75,0x6e,0x67,0x58,0x51,0x4a,0x43,0x34,0x3d,0x26,0x2f,0x10,0x19,0x02,0x0b }, + { 0xd7,0xde,0xc5,0xcc,0xf3,0xfa,0xe1,0xe8,0x9f,0x96,0x8d,0x84,0xbb,0xb2,0xa9,0xa0 }, + { 0x47,0x4e,0x55,0x5c,0x63,0x6a,0x71,0x78,0x0f,0x06,0x1d,0x14,0x2b,0x22,0x39,0x30 }, + { 0x9a,0x93,0x88,0x81,0xbe,0xb7,0xac,0xa5,0xd2,0xdb,0xc0,0xc9,0xf6,0xff,0xe4,0xed }, + { 0x0a,0x03,0x18,0x11,0x2e,0x27,0x3c,0x35,0x42,0x4b,0x50,0x59,0x66,0x6f,0x74,0x7d }, + { 0xa1,0xa8,0xb3,0xba,0x85,0x8c,0x97,0x9e,0xe9,0xe0,0xfb,0xf2,0xcd,0xc4,0xdf,0xd6 }, + { 0x31,0x38,0x23,0x2a,0x15,0x1c,0x07,0x0e,0x79,0x70,0x6b,0x62,0x5d,0x54,0x4f,0x46 }}; + + +AES::uint8 AES::gf_mul11[16][16] = { + { 0x00,0x0b,0x16,0x1d,0x2c,0x27,0x3a,0x31,0x58,0x53,0x4e,0x45,0x74,0x7f,0x62,0x69 }, + { 0xb0,0xbb,0xa6,0xad,0x9c,0x97,0x8a,0x81,0xe8,0xe3,0xfe,0xf5,0xc4,0xcf,0xd2,0xd9 }, + { 0x7b,0x70,0x6d,0x66,0x57,0x5c,0x41,0x4a,0x23,0x28,0x35,0x3e,0x0f,0x04,0x19,0x12 }, + { 0xcb,0xc0,0xdd,0xd6,0xe7,0xec,0xf1,0xfa,0x93,0x98,0x85,0x8e,0xbf,0xb4,0xa9,0xa2 }, + { 0xf6,0xfd,0xe0,0xeb,0xda,0xd1,0xcc,0xc7,0xae,0xa5,0xb8,0xb3,0x82,0x89,0x94,0x9f }, + { 0x46,0x4d,0x50,0x5b,0x6a,0x61,0x7c,0x77,0x1e,0x15,0x08,0x03,0x32,0x39,0x24,0x2f }, + { 0x8d,0x86,0x9b,0x90,0xa1,0xaa,0xb7,0xbc,0xd5,0xde,0xc3,0xc8,0xf9,0xf2,0xef,0xe4 }, + { 0x3d,0x36,0x2b,0x20,0x11,0x1a,0x07,0x0c,0x65,0x6e,0x73,0x78,0x49,0x42,0x5f,0x54 }, + { 0xf7,0xfc,0xe1,0xea,0xdb,0xd0,0xcd,0xc6,0xaf,0xa4,0xb9,0xb2,0x83,0x88,0x95,0x9e }, + { 0x47,0x4c,0x51,0x5a,0x6b,0x60,0x7d,0x76,0x1f,0x14,0x09,0x02,0x33,0x38,0x25,0x2e }, + { 0x8c,0x87,0x9a,0x91,0xa0,0xab,0xb6,0xbd,0xd4,0xdf,0xc2,0xc9,0xf8,0xf3,0xee,0xe5 }, + { 0x3c,0x37,0x2a,0x21,0x10,0x1b,0x06,0x0d,0x64,0x6f,0x72,0x79,0x48,0x43,0x5e,0x55 }, + { 0x01,0x0a,0x17,0x1c,0x2d,0x26,0x3b,0x30,0x59,0x52,0x4f,0x44,0x75,0x7e,0x63,0x68 }, + { 0xb1,0xba,0xa7,0xac,0x9d,0x96,0x8b,0x80,0xe9,0xe2,0xff,0xf4,0xc5,0xce,0xd3,0xd8 }, + { 0x7a,0x71,0x6c,0x67,0x56,0x5d,0x40,0x4b,0x22,0x29,0x34,0x3f,0x0e,0x05,0x18,0x13 }, + { 0xca,0xc1,0xdc,0xd7,0xe6,0xed,0xf0,0xfb,0x92,0x99,0x84,0x8f,0xbe,0xb5,0xa8,0xa3 }}; + + +AES::uint8 AES::gf_mul13[16][16] = { + { 0x00,0x0d,0x1a,0x17,0x34,0x39,0x2e,0x23,0x68,0x65,0x72,0x7f,0x5c,0x51,0x46,0x4b }, + { 0xd0,0xdd,0xca,0xc7,0xe4,0xe9,0xfe,0xf3,0xb8,0xb5,0xa2,0xaf,0x8c,0x81,0x96,0x9b }, + { 0xbb,0xb6,0xa1,0xac,0x8f,0x82,0x95,0x98,0xd3,0xde,0xc9,0xc4,0xe7,0xea,0xfd,0xf0 }, + { 0x6b,0x66,0x71,0x7c,0x5f,0x52,0x45,0x48,0x03,0x0e,0x19,0x14,0x37,0x3a,0x2d,0x20 }, + { 0x6d,0x60,0x77,0x7a,0x59,0x54,0x43,0x4e,0x05,0x08,0x1f,0x12,0x31,0x3c,0x2b,0x26 }, + { 0xbd,0xb0,0xa7,0xaa,0x89,0x84,0x93,0x9e,0xd5,0xd8,0xcf,0xc2,0xe1,0xec,0xfb,0xf6 }, + { 0xd6,0xdb,0xcc,0xc1,0xe2,0xef,0xf8,0xf5,0xbe,0xb3,0xa4,0xa9,0x8a,0x87,0x90,0x9d }, + { 0x06,0x0b,0x1c,0x11,0x32,0x3f,0x28,0x25,0x6e,0x63,0x74,0x79,0x5a,0x57,0x40,0x4d }, + { 0xda,0xd7,0xc0,0xcd,0xee,0xe3,0xf4,0xf9,0xb2,0xbf,0xa8,0xa5,0x86,0x8b,0x9c,0x91 }, + { 0x0a,0x07,0x10,0x1d,0x3e,0x33,0x24,0x29,0x62,0x6f,0x78,0x75,0x56,0x5b,0x4c,0x41 }, + { 0x61,0x6c,0x7b,0x76,0x55,0x58,0x4f,0x42,0x09,0x04,0x13,0x1e,0x3d,0x30,0x27,0x2a }, + { 0xb1,0xbc,0xab,0xa6,0x85,0x88,0x9f,0x92,0xd9,0xd4,0xc3,0xce,0xed,0xe0,0xf7,0xfa }, + { 0xb7,0xba,0xad,0xa0,0x83,0x8e,0x99,0x94,0xdf,0xd2,0xc5,0xc8,0xeb,0xe6,0xf1,0xfc }, + { 0x67,0x6a,0x7d,0x70,0x53,0x5e,0x49,0x44,0x0f,0x02,0x15,0x18,0x3b,0x36,0x21,0x2c }, + { 0x0c,0x01,0x16,0x1b,0x38,0x35,0x22,0x2f,0x64,0x69,0x7e,0x73,0x50,0x5d,0x4a,0x47 }, + { 0xdc,0xd1,0xc6,0xcb,0xe8,0xe5,0xf2,0xff,0xb4,0xb9,0xae,0xa3,0x80,0x8d,0x9a,0x97 }}; + + +AES::uint8 AES::gf_mul14[16][16] = { + { 0x00,0x0e,0x1c,0x12,0x38,0x36,0x24,0x2a,0x70,0x7e,0x6c,0x62,0x48,0x46,0x54,0x5a }, + { 0xe0,0xee,0xfc,0xf2,0xd8,0xd6,0xc4,0xca,0x90,0x9e,0x8c,0x82,0xa8,0xa6,0xb4,0xba }, + { 0xdb,0xd5,0xc7,0xc9,0xe3,0xed,0xff,0xf1,0xab,0xa5,0xb7,0xb9,0x93,0x9d,0x8f,0x81 }, + { 0x3b,0x35,0x27,0x29,0x03,0x0d,0x1f,0x11,0x4b,0x45,0x57,0x59,0x73,0x7d,0x6f,0x61 }, + { 0xad,0xa3,0xb1,0xbf,0x95,0x9b,0x89,0x87,0xdd,0xd3,0xc1,0xcf,0xe5,0xeb,0xf9,0xf7 }, + { 0x4d,0x43,0x51,0x5f,0x75,0x7b,0x69,0x67,0x3d,0x33,0x21,0x2f,0x05,0x0b,0x19,0x17 }, + { 0x76,0x78,0x6a,0x64,0x4e,0x40,0x52,0x5c,0x06,0x08,0x1a,0x14,0x3e,0x30,0x22,0x2c }, + { 0x96,0x98,0x8a,0x84,0xae,0xa0,0xb2,0xbc,0xe6,0xe8,0xfa,0xf4,0xde,0xd0,0xc2,0xcc }, + { 0x41,0x4f,0x5d,0x53,0x79,0x77,0x65,0x6b,0x31,0x3f,0x2d,0x23,0x09,0x07,0x15,0x1b }, + { 0xa1,0xaf,0xbd,0xb3,0x99,0x97,0x85,0x8b,0xd1,0xdf,0xcd,0xc3,0xe9,0xe7,0xf5,0xfb }, + { 0x9a,0x94,0x86,0x88,0xa2,0xac,0xbe,0xb0,0xea,0xe4,0xf6,0xf8,0xd2,0xdc,0xce,0xc0 }, + { 0x7a,0x74,0x66,0x68,0x42,0x4c,0x5e,0x50,0x0a,0x04,0x16,0x18,0x32,0x3c,0x2e,0x20 }, + { 0xec,0xe2,0xf0,0xfe,0xd4,0xda,0xc8,0xc6,0x9c,0x92,0x80,0x8e,0xa4,0xaa,0xb8,0xb6 }, + { 0x0c,0x02,0x10,0x1e,0x34,0x3a,0x28,0x26,0x7c,0x72,0x60,0x6e,0x44,0x4a,0x58,0x56 }, + { 0x37,0x39,0x2b,0x25,0x0f,0x01,0x13,0x1d,0x47,0x49,0x5b,0x55,0x7f,0x71,0x63,0x6d }, + { 0xd7,0xd9,0xcb,0xc5,0xef,0xe1,0xf3,0xfd,0xa7,0xa9,0xbb,0xb5,0x9f,0x91,0x83,0x8d }}; + + + + +void AES::CopyToData(const AES::uint8 * state) +{ +int x, y, index = 0; + + for(x=0 ; x<4 ; ++x) + for(y=0 ; y<4 ; ++y) + data[y][x] = state[index++]; +} + + + +void AES::CopyFromData(AES::uint8 * state) +{ +int x, y, index = 0; + + for(x=0 ; x<4 ; ++x) + for(y=0 ; y<4 ; ++y) + state[index++] = data[y][x]; +} + + +void AES::CopyFromData(std::vector & out, bool clear) +{ +int x, y; + + if( clear ) + out.clear(); + + if( out.size() + 16 > out.capacity() ) + out.reserve(out.size() + 16); + + for(x=0 ; x<4 ; ++x) + for(y=0 ; y<4 ; ++y) + out.push_back(data[y][x]); +} + + + +void AES::PrintData() +{ +int x, y; +char buf[20]; + + for(y=0 ; y<4 ; ++y) + { + for(x=0 ; x<4 ; ++x) + { + sprintf(buf, "%02x ", data[y][x]); + std::cout << buf; + } + + std::cout << std::endl; + } +} + + +void AES::PrintKey(int xs) +{ +int x, y; +char buf[20]; + + for(y=0 ; y<4 ; ++y) + { + for(x=xs ; x> 4; + int x = (v & 0x0f); + +return sbox[y][x]; +} + + + +void AES::SubBytes() +{ +int x, y; + + for(y=0 ; y<4 ; ++y) + for(x=0 ; x<4 ; ++x) + data[y][x] = SubBytes(data[y][x]); +} + + + +void AES::ShiftRows1(AES::uint8 tab[4]) +{ + uint8 temp = tab[0]; + + tab[0] = tab[1]; + tab[1] = tab[2]; + tab[2] = tab[3]; + tab[3] = temp; +} + + + +void AES::ShiftRows2(AES::uint8 tab[4]) +{ + uint8 temp1 = tab[0]; + uint8 temp2 = tab[1]; + + tab[0] = tab[2]; + tab[1] = tab[3]; + tab[2] = temp1; + tab[3] = temp2; +} + + + +void AES::ShiftRows3(AES::uint8 tab[4]) +{ + uint8 temp = tab[3]; + + tab[3] = tab[2]; + tab[2] = tab[1]; + tab[1] = tab[0]; + tab[0] = temp; +} + + + +void AES::ShiftRows() +{ + ShiftRows1(data[1]); + ShiftRows2(data[2]); + ShiftRows3(data[3]); +} + + + +AES::uint8 AES::MixColumns2(AES::uint8 v) +{ + bool high_bit = (v & 0x80) != 0; + + v = v << 1; + + if( high_bit ) + v = v ^ 0x1b; + +return v; +} + + + +AES::uint8 AES::MixColumns3(AES::uint8 v) +{ + bool high_bit = (v & 0x80) != 0; + + AES::uint8 vold = v; + + v = (v << 1) ^ vold; + + if( high_bit ) + v = v ^ 0x1b; + +return v; +} + + + +AES::uint8 AES::MixColumns(int type, AES::uint8 value) +{ + switch(type) + { + case 2: + return MixColumns2(value); + + case 3: + return MixColumns3(value); + + case 1: + default: + return value; + } +} + + + +void AES::MixColumns() +{ +int x, y, i; +uint8 v; +uint8 temp[4]; + + for(x=0 ; x<4 ; ++x) + { + for(y=0 ; y<4 ; ++y) + { + v = 0; + + for(i=0 ; i<4 ; ++i) + v ^= MixColumns(mixcolumntab[y][i], data[i][x]); + + temp[y] = v; + } + + for(y=0 ; y<4 ; ++y) + data[y][x] = temp[y]; + + } +} + + + + +bool AES::Key(AES::uint8 * key_src, int key_length) +{ +int x, y, index = 0; + + key_len = key_length; + + if( key_len == 16 ) + { + key_col = 4; + round = 10; + } + else + if( key_len == 24 ) + { + key_col = 6; + round = 12; + } + else + if( key_len == 32 ) + { + key_col = 8; + round = 14; + } + else + { + return false; + } + + for(x=0 ; x 6 && i % key_col == 4 ) + { + SubWordKey(i); + } + + for(y=0 ; y<4 ; ++y) + key[y][i] ^= key[y][i-key_col]; + + + + //PrintKey3(i); + + /* + if( i % key_col == 0 ) + { + std::cout << " ---- " << (rcon_index-1) << std::endl; + PrintKey2(i-key_col); + } + */ + } + + //std::cout << " ---- " << rcon_index << std::endl; + //PrintKey2(i-key_col); +} + + + +void AES::AddRoundKey(int xs) +{ +int x, y; + + for(y=0 ; y<4 ; ++y) + for(x=0 ; x<4 ; ++x) + data[y][x] ^= key[y][xs+x]; +} + + + +void AES::EncodeData() +{ +int i; + +// std::cout << " input data " << std::endl; +// PrintData(); + + AddRoundKey(0); + +// std::cout << " first round key " << std::endl; +// PrintData(); + + for(i=0 ; i=0 ; --i) + { + InvShiftRows(); + +// std::cout << " after invshiftrows, i= " << i << std::endl; +// PrintData(); + + InvSubBytes(); + +// std::cout << " after invsubbutes, i= " << i << std::endl; +// PrintData(); + + AddRoundKey(i*4); + +// std::cout << " after add round key, i= " << i << std::endl; +// PrintData(); + + if( i != 0 ) + { + InvMixColumns(); + +// std::cout << " after inv mix columns, i= " << i << std::endl; +// PrintData(); + } + } +} + + + +/* + + +*/ + +bool AES::Encode(AES::uint8 * block, size_t len) +{ + if( len % 16 != 0 ) + return false; + + while( len > 0 ) + { + CopyToData(block); + EncodeData(); + CopyFromData(block); + + len -= 16; + block += 16; + } + +return true; +} + + +bool AES::Decode(AES::uint8 * block, size_t len) +{ + if( len % 16 != 0 ) + return false; + + while( len > 0 ) + { + CopyToData(block); + DecodeData(); + CopyFromData(block); + + len -= 16; + block += 16; + } + +return true; +} + + + + + +void AES::IntToBuf(AES::uint8 * buf, AES::uint16 value) +{ + buf[0] = value & 0xff; + buf[1] = (value >> 8) & 0xff; +} + +void AES::IntToBuf(AES::uint8 * buf, AES::uint32 value) +{ + buf[0] = value & 0xff; + buf[1] = (value >> 8) & 0xff; + buf[2] = (value >> 16) & 0xff; + buf[3] = (value >> 24) & 0xff; +} + + +void AES::CreateHeader(TiHeader & header, const AES::uint8 * block, size_t len, const std::string & name) +{ + header.signature = int('t') + (int('i') << 8); + + // first padding from 3 to 9 + header.pad1 = (6 * rand()) / RAND_MAX + 3; + header.all_len = 12 + header.pad1 + name.size() + len; + + header.pad2 = 0; + + if( (header.all_len % 16) != 0 ) + header.pad2 = 16 - (header.all_len % 16); + + header.all_len += header.pad2; + header.checksum_before = Checksum(block, len); + header.checksum_after = 0; + header.name_len = name.size(); +} + + +void AES::PutHeader(const TiHeader & header, std::vector & out) +{ +uint8 buf[16]; + + IntToBuf(buf, header.signature); + out.push_back(buf[0]); + out.push_back(buf[1]); + + // space for checksum after encoding + out.push_back(0); + out.push_back(0); + out.push_back(0); + out.push_back(0); + + IntToBuf(buf, header.pad1); + IntToBuf(buf+2, header.pad2); + IntToBuf(buf+4, header.checksum_before); + IntToBuf(buf+8, header.name_len); + + for(int i=12 ; i<16 ; ++i) + buf[i] = 0; + + CopyToData(buf); +} + + +void AES::PutChecksumAfter(std::vector & out) +{ + if( out.size() < 7 ) + return; // something wrong + + // checksum starting from 6th byte + AES::uint32 checksum_after = Checksum(&out[6], out.size()-6); + IntToBuf(&out[2], checksum_after); +} + + +AES::uint32 AES::Checksum(const uint8 * block, size_t len) +{ +uint32 sum = 0; + + for(size_t i=0 ; i & out) +{ +AES::uint16 index = 0; + + while( true ) + { + for( ; x<4 ; ++x) + { + for(; y<4 ; ++y) + { + if( index < pad ) + { + data[y][x] = (rand() * 255) / RAND_MAX; + index += 1; + } + else + { + return; + } + } + + y = 0; + } + + x = 0; + EncodeData(); + CopyFromData(out, false); + } +} + + +void AES::EncodeName(int & y, int & x, const std::string & name, std::vector & out) +{ +size_t index = 0; + + while( true ) + { + for( ; x<4 ; ++x) + { + for(; y<4 ; ++y) + { + if( index < name.size() ) + { + data[y][x] = name[index]; + index += 1; + } + else + { + return; + } + } + + y = 0; + } + + x = 0; + EncodeData(); + CopyFromData(out, false); + } +} + + + +void AES::EncodeData(int & y, int & x, const AES::uint8 * block, size_t len, std::vector & out) +{ +size_t index = 0; + + while( true ) + { + for( ; x<4 ; ++x) + { + for(; y<4 ; ++y) + { + if( index < len ) + { + data[y][x] = block[index]; + index += 1; + } + else + { + return; + } + } + + y = 0; + } + + x = 0; + EncodeData(); + CopyFromData(out, false); + } +} + + + + + +/* + (not encrypted) + 2 bytes: signature "ti" + 4 bytes: data checksum after encoding + --- + 6 bytes + (encrypted) + 2 bytes: first padding length (from 3 to 9) + 2 bytes: last padding length (can be zero) + 4 bytes: data checksum before encoding + 4 bytes: name string length (it can be a name of a file or just zero means an empty string) + --- + 12 bytes (18 bytes alltogether) + + ... bytes: first padding + ... bytes: name string + ... bytes: data + ... bytes: last padding +*/ +bool AES::Encode(const AES::uint8 * block, size_t len, const std::string & name, std::vector & out) +{ +TiHeader header; + + out.clear(); + CreateHeader(header, block, len, name); + PutHeader(header, out); + + if( out.capacity() < header.all_len ) + out.reserve(header.all_len); + + // skipping first 12 bytes from 'data' + int y = 0; + int x = 3; + + EncodePad (y, x, header.pad1, out); + EncodeName(y, x, name, out); + EncodeData(y, x, block, len, out); + EncodePad (y, x, header.pad2, out); + PutChecksumAfter(out); + +return true; +} + + +bool AES::Encode(const std::vector & block, const std::string & name, std::vector & out) +{ + if( block.empty() ) + return Encode(0, 0, name, out); + else + return Encode(&block[0], block.size(), name, out); +} + + +/* +*/ +void AES::ReadHeader(TiHeader & header, const AES::uint8 * block) +{ + header.signature = (uint16(block[1]) << 8) + uint16(block[0]); + header.checksum_after = (uint32(block[5]) << 24) + (uint32(block[4]) << 16) + (uint32(block[3]) << 8) + uint32(block[2]); + + header.pad1 = (uint16(data[1][0]) << 8) + uint16(data[0][0]); + header.pad2 = (uint16(data[3][0]) << 8) + uint16(data[2][0]); + header.checksum_before = (uint32(data[3][1]) << 24) + (uint32(data[2][1]) << 16) + (uint32(data[1][1]) << 8) + uint32(data[0][1]); + header.name_len = (uint32(data[3][2]) << 24) + (uint32(data[2][2]) << 16) + (uint32(data[1][2]) << 8) + uint32(data[0][2]); +} + + + +void AES::DecodePad(int & y, int & x, const AES::uint8 * & block, size_t & len, AES::uint16 pad) +{ +AES::uint16 index = 0; + + while( true ) + { + for( ; x<4 ; ++x) + { + for( ; y<4 ; ++y) + { + if( index < pad ) + { + index += 1; + } + else + { + return; + } + } + + y = 0; + } + + x = 0; + + if( len > 0 ) + { + CopyToData(block); + DecodeData(); + block += 16; + len -= 16; + } + } +} + + +void AES::DecodeName(int & y, int & x, const AES::uint8 * & block, size_t & len, AES::uint32 name_len, std::string & name) +{ +AES::uint32 index = 0; + + while( true ) + { + for( ; x<4 ; ++x) + { + for( ; y<4 ; ++y) + { + if( index < name_len ) + { + index += 1; + name += static_cast(data[y][x]); + } + else + { + return; + } + } + + y = 0; + } + + x = 0; + + if( len > 0 ) + { + CopyToData(block); + DecodeData(); + block += 16; + len -= 16; + } + } +} + + +void AES::DecodeData(int & y, int & x, const AES::uint8 * & block, size_t & len, size_t data_len, std::vector & out) +{ +size_t index = 0; + + while( true ) + { + for( ; x<4 ; ++x) + { + for( ; y<4 ; ++y) + { + if( index < data_len ) + { + index += 1; + out.push_back(data[y][x]); + } + else + { + return; + } + } + + y = 0; + } + + x = 0; + + if( len > 0 ) + { + CopyToData(block); + DecodeData(); + block += 16; + len -= 16; + } + } +} + + + +bool AES::CheckSignatureAndChecksumAfter(const TiHeader & header, const AES::uint8 * block, size_t len) +{ + if( ((header.signature >> 8) & 0xff) != 'i' || (header.signature & 0xff) != 't' ) + return false; + + AES::uint32 ch_after = Checksum(block+6, len-6); + +return ch_after == header.checksum_after; +} + + +bool AES::CheckChecksumBefore(const TiHeader & header, std::vector & out) +{ + AES::uint32 ch_before = 0; + + if( !out.empty() ) + ch_before = Checksum(&out[0], out.size()); + +return ch_before == header.checksum_before; +} + + +bool AES::Decode(const AES::uint8 * block, size_t len, std::string & name, std::vector & out) +{ +TiHeader header; + + name.clear(); + out.clear(); + + // incorrect size + if( len < 18 || (len - 6) % 16 != 0) + return false; + + CopyToData(block+6); + DecodeData(); + ReadHeader(header, block); + + if( !CheckSignatureAndChecksumAfter(header, block, len) ) + return false; + + size_t min_size = 18 + header.pad1 + header.name_len + header.pad2; + + if( len < min_size ) + return false; + + size_t data_len = len - 18 - header.pad1 - header.name_len - header.pad2; + int y = 0; + int x = 3; + + // skipping non encrypted part and first block + block += (6 + 16); + len -= (6 + 16); + + DecodePad (y, x, block, len, header.pad1); + DecodeName(y, x, block, len, header.name_len, name); + DecodeData(y, x, block, len, data_len, out); + +return CheckChecksumBefore(header, out); +} + + +bool AES::Decode(const std::vector & block, std::string & name, std::vector & out) +{ + if( block.empty() ) + return Decode(0, 0, name, out); + else + return Decode(&block[0], block.size(), name, out); +} + + + + + + + + + + + + + + + + + + + + +/* + algorithm description: http://www.samiam.org/galois.html +*/ +AES::uint8 AES::GaloisMultiply(AES::uint8 a, AES::uint8 b) +{ +int i; +uint8 p = 0; + + for(i=0; i<8 ;++i) + { + if(b & 1) + p ^= a; + + bool a_high_bit = (a & 0x80) != 0; + + a = a << 1; + + if( a_high_bit ) + a ^= 0x1b; + + b = b >> 1; + } + +return p; +} + + +bool AES::CheckGFTable(int value, AES::uint8 gf_mul[16][16]) +{ +int x,y; +bool ok = true; + + for(y=0 ; y<16 ; ++y) + { + for(x=0 ; x<16 ; ++x) + { + int v1 = gf_mul[y][x]; + int v2 = GaloisMultiply(value, y*16 + x); + + if( v1 != v2 ) + { + std::cout << "error: y: " << y << ", x: " << x << ", v1: " << v1 << ", v2: " << v2 << std::endl; + ok = false; + } + } + } + +return ok; +} + + +bool AES::CheckGFTables() +{ +bool ok9, ok11, ok13, ok14; + + ok9 = CheckGFTable(9, gf_mul9); + ok11 = CheckGFTable(11, gf_mul11); + ok13 = CheckGFTable(13, gf_mul13); + ok14 = CheckGFTable(14, gf_mul14); + + bool ok = ok9 && ok11 && ok13 && ok14; + + if( ok ) + std::cout << "All GF tables are good" << std::endl; + +return ok; +} + + + + +} // namespace Tito + + diff --git a/aes.h b/aes.h new file mode 100755 index 0000000..c8c8014 --- /dev/null +++ b/aes.h @@ -0,0 +1,239 @@ +/* + * This file is a part of Tito - a cryptography library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2012, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef headerfile_tito_aes +#define headerfile_tito_aes + +#include +#include + + +namespace Tito +{ + + +class AES +{ +public: + +typedef unsigned char uint8; +typedef unsigned short int uint16; +typedef unsigned int uint32; + + + + // 'state' + // 128 bits data block (16 bytes) + // this is input/output buffer for encoding/decoding + uint8 data[4][4]; + + // copying 16 bytes (128bits) buffer to/from 'data' table + void CopyToData(const uint8 * state); + void CopyFromData(uint8 * state); + void CopyFromData(std::vector & out, bool clear = true); + + // setting a new key + // key_length should be either: 16, 24 or 32 + // if the key has incorrect length the method does nothing and returns false + bool Key(AES::uint8 * key_src, int key_length); + + // encoding/decoding one 128 bits block + // you can set the value for encoding/decoding either by directly + // setting 'data' table or using CopyToData method + void EncodeData(); + void DecodeData(); + + // encoding/decoding block of data + // the length should be multiplication of 16 (128bits) + // the method returns false if length is incorrect + bool Encode(uint8 * block, size_t len); + bool Decode(uint8 * block, size_t len); + + // encoding/decoding block of data + // there is not any restrictions to the length + // we are using our own header in which we remember the length + // some control sums, how many padding bytes were used + // Encode returns always true + // Decode returns false is the control sums are different from original in the header + bool Encode(const uint8 * block, size_t len, const std::string & name, std::vector & out); + bool Encode(const std::vector & block, const std::string & name, std::vector & out); + bool Decode(const uint8 * block, size_t len, std::string & name, std::vector & out); + bool Decode(const std::vector & block, std::string & name, std::vector & out); + + // printing 'data' tab + // for debug purposes + void PrintData(); + void PrintKey(int xs); + void PrintKey2(int xs); + void PrintKey3(int xs); + bool CheckGFTables(); + + + +private: + + + // key (either 128 or 192 or 256 bits) + // and a space for key expansion + uint8 key[4][60]; + + // key length (in bytes) + // 16 for 128 bits + // 24 for 192 bits + // 32 for 256 bits + int key_len; + + // key columns + // 4 for 128 bits key + // 6 for 192 bits key + // 8 for 256 bits key + int key_col; + + // how many rounds should be performed + // 10 for 128 bits key + // 12 for 192 bits key + // 14 for 256 bits key + int round; + + // sbox and inverse sbox tables (256 bytes each) + static uint8 sbox[16][16]; + static uint8 invsbox[16][16]; + + // a table for mixcolumn state + static int mixcolumntab[4][4]; + + static uint8 Rcon[10]; + + + static int invmixcolumntab[4][4]; + + static uint8 gf_mul9[16][16]; + static uint8 gf_mul11[16][16]; + static uint8 gf_mul13[16][16]; + static uint8 gf_mul14[16][16]; + + // returning a coresponding value from sbox table + uint8 SubBytes(AES::uint8 v); + + // making the SubBytes algorithm on all items in 'data' table + void SubBytes(); + + // performing shift rows by 1 item + void ShiftRows1(AES::uint8 tab[4]); + + // performing shift rows by 2 items + void ShiftRows2(AES::uint8 tab[4]); + + // performing shift rows by 3 item + void ShiftRows3(AES::uint8 tab[4]); + + // performing shift rows on 'data' table + void ShiftRows(); + + + uint8 MixColumns2(uint8 v); + uint8 MixColumns3(uint8 v); + uint8 MixColumns(int type, uint8 value); + void MixColumns(); + + + + void RotKey(int i); + void SubWordKey(int i); + void KeyExpansion(); + + void AddRoundKey(int xs); + + + + /* inverse */ + + void InvShiftRows1(uint8 tab[4]); + void InvShiftRows2(uint8 tab[4]); + void InvShiftRows3(uint8 tab[4]); + void InvShiftRows(); + + uint8 InvSubBytes(uint8 v); + void InvSubBytes(); + void InvMixColumns(); + + uint8 InvMixColumns(uint8 gf_mul[16][16], uint8 v); + uint8 InvMixColumns(int type, uint8 value); + + + /* for debug */ + + uint8 GaloisMultiply(uint8 a, uint8 b); + bool CheckGFTable(int value, uint8 gf_mul[16][16]); + + + struct TiHeader + { + AES::uint16 signature; + AES::uint16 pad1; + AES::uint16 pad2; + AES::uint32 checksum_before; + AES::uint32 checksum_after; + AES::uint32 name_len; + size_t all_len; + }; + + void IntToBuf(uint8 * buf, uint16 value); + void IntToBuf(uint8 * buf, uint32 value); + void CreateHeader(TiHeader & header, const uint8 * block, size_t len, const std::string & name); + void PutHeader(const TiHeader & header, std::vector & out); + void PutChecksumAfter(std::vector & out); + uint32 Checksum(const uint8 * block, size_t len); + void EncodePad(int & y, int & x, uint16 pad, std::vector & out); + void EncodeName(int & y, int & x, const std::string & name, std::vector & out); + void EncodeData(int & y, int & x, const uint8 * block, size_t len, std::vector & out); + + void ReadHeader(TiHeader & header, const uint8 * block); + void DecodePad(int & y, int & x, const uint8 * & block, size_t & len, uint16 pad); + void DecodeName(int & y, int & x, const uint8 * & block, size_t & len, uint32 name_len, std::string & name); + void DecodeData(int & y, int & x, const uint8 * & block, size_t & len, size_t data_len, std::vector & out); + + bool CheckSignatureAndChecksumAfter(const TiHeader & header, const uint8 * block, size_t len); + bool CheckChecksumBefore(const TiHeader & header, std::vector & out); +}; + + + +} // namespace Tito + + +#endif diff --git a/base64.cpp b/base64.cpp new file mode 100755 index 0000000..56ec936 --- /dev/null +++ b/base64.cpp @@ -0,0 +1,281 @@ +/* + * This file is a part of Tito - a cryptography library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2012, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "base64.h" + + +namespace Tito +{ + + +// 64 characters +const char * Base64::tabbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + + +Base64::Base64() +{ + padding = '='; + tabbase64_len = 64; + not_existing = 256; // first 8 bits are zero +} + + + +void Base64::SetPadding(char c) +{ + for(size_t i=0 ; i(s); + + tab4[0] = tab4[1] = tab4[2] = tab4[3] = 64; + + if( len == 0 ) + return; + + tab4[0] = tab3[0] >> 2; + tab4[1] = (tab3[0] & 0x03) << 4; + + if( len == 1 ) + return; + + tab4[1] = tab4[1] | ((tab3[1] & 0xf0) >> 4); + tab4[2] = (tab3[1] & 0x0f) << 2; + + if( len == 2 ) + return; + + tab4[2] = (tab4[2]) | ((tab3[2] & 0xc0) >> 6); + tab4[3] = tab3[2] & 0x3f; +} + + + +void Base64::ConvertFrom4to3Pieces(const unsigned int * tab4, unsigned int * tab3) +{ + /* + tab4[0] and tab4[1] are always different from 'not_existing' + */ + + tab3[0] = ((tab4[0] & 0x3f) << 2) | (( tab4[1] & 0x30 ) >> 4); + tab3[1] = tab3[2] = not_existing; + + if( tab4[2] == not_existing ) + return; + + tab3[1] = ((tab4[1] & 0x0f) << 4) | (( tab4[2] & 0x3c ) >> 2); + + if( tab4[3] == not_existing ) + return; + + tab3[2] = ((tab4[2] & 0x03) << 6) | (tab4[3] & 0x3f); +} + + + + + +bool Base64::CharFromBase64(unsigned int from, unsigned int & to) +{ + if( from>='A' && from<='Z' ) + { + to = from-'A'; + return true; + } + else + if( from>='a' && from<='z' ) + { + to = from - 'a' + 'Z'-'A' + 1; + return true; + } + else + if( from>='0' && from<='9' ) + { + to = from - '0' + 'Z'-'A' + 1 + 'z'-'a' + 1; + return true; + } + else + if( from == '+' ) + { + to = tabbase64_len - 2; + return true; + } + else + if( from == '/' ) + { + to = tabbase64_len - 1; + return true; + } + + /* + such character does not exist in tabbase64 table + */ + return false; +} + + + +bool Base64::Make4pieces(const char * s, unsigned int * tab4) +{ + for(size_t i=0 ; i<4 ; ++i) + { + if( s[i] == padding ) + tab4[i] = not_existing; + else + if( !CharFromBase64(s[i], tab4[i]) ) + return false; + } + +return true; +} + + + + +void Base64::Save4PiecesToString(std::string & s, const unsigned int * tab4) +{ + for(int i=0 ; i<4 ; ++i) + { + if( tab4[i] < tabbase64_len ) + s += tabbase64[tab4[i]]; + else + s += padding; + } +} + + + +void Base64::Save3PiecesToString(std::string & s, const unsigned int * tab3) +{ + for(int i=0 ; i<3 ; ++i) + { + if( tab3[i] != not_existing ) + s += tab3[i]; + } +} + + + + +/* +*/ +void Base64::Encode(const char * in, size_t len, std::string & out) +{ +unsigned int tab4[4]; + + out.clear(); + size_t new_size = len + len/3 + 3; + out.reserve(new_size); + + for(size_t i=0 ; i < len ; i+=3) + { + Convert3to4Pieces(in+i, len-i, tab4); + Save4PiecesToString(out, tab4); + } +} + + +void Base64::Encode(const char * in, std::string & out) +{ + size_t len = strlen(in); + Encode(in, len, out); +} + + +void Base64::Encode(const std::string & in, std::string & out) +{ + Encode(in.c_str(), in.size(), out); +} + + + + + + +bool Base64::Decode(const char * in, size_t len, std::string & out) +{ +unsigned int tab3[3]; +unsigned int tab4[4]; + + out.clear(); + size_t new_size = len - len/3 + 3; + out.reserve(new_size); + + if( len % 4 != 0 ) + return false; + + for(size_t i=0 ; i + */ + +/* + * Copyright (c) 2012, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef headerfile_tito_base64 +#define headerfile_tito_base64 + +#include + + +namespace Tito +{ + + +class Base64 +{ +public: + + Base64(); + + // default '='; + void SetPadding(char c); + + void Encode(const char * in, size_t len, std::string & out); + void Encode(const char * in, std::string & out); + void Encode(const std::string & in, std::string & out); + + bool Decode(const char * in, size_t len, std::string & out); + bool Decode(const char * in, std::string & out); + bool Decode(const std::string & in, std::string & out); + + + +private: + + static const char * tabbase64; + size_t tabbase64_len; + char padding; + unsigned int not_existing; + + void Convert3to4Pieces(const char * s, size_t len, unsigned int * tab4); + void ConvertFrom4to3Pieces(const unsigned int * tab4, unsigned int * tab3); + bool CharFromBase64(unsigned int from, unsigned int & to); + bool Make4pieces(const char * s, unsigned int * tab4); + void Save4PiecesToString(std::string & s, const unsigned int * tab4); + void Save3PiecesToString(std::string & s, const unsigned int * tab3); + +}; + + + +} // namespace Tito + + + +#endif + diff --git a/crypto.cpp b/crypto.cpp new file mode 100755 index 0000000..15407c5 --- /dev/null +++ b/crypto.cpp @@ -0,0 +1,163 @@ +/* + * This file is a part of Tito - a cryptography library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2012, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "crypto.h" + +// !! FIX ME +//#include "log.h" + +#include "../ezc/src/utf8.h" +#include "misc.h" + + +namespace Tito +{ + + + +bool Crypto::SetAESKey(unsigned char aes_key[32]) +{ + if( !aes.Key(aes_key, 32) ) + { + //log << log1 << "problem with AES key" << logend; + return false; + } + +return true; +} + + + +void Crypto::Crypt(const std::wstring & in, std::wstring & out) +{ + Ezc::WideToUTF8(in, utf8_str); + aes.Encode((const unsigned char*)utf8_str.c_str(), utf8_str.size(), aes_name, uint8_tab); + + base64_str.clear(); + + if( !uint8_tab.empty() ) + base64.Encode((const char*)&uint8_tab[0], uint8_tab.size(), base64_str); + + AssignString(base64_str, out); + Clear(); +} + + +void Crypto::Crypt(const std::vector & in, std::string & out) +{ + aes.Encode((const unsigned char*)&in[0], in.size(), aes_name, uint8_tab); + base64.Encode((const char*)&uint8_tab[0], uint8_tab.size(), out); + Clear(); +} + + + +bool Crypto::Decrypt(const std::wstring & in, std::wstring & out) +{ + out.clear(); + + if( in.empty() ) + return true; + + AssignString(in, base64_str); + base64.Decode(base64_str, aes_str); + + if( aes.Decode((const unsigned char *)aes_str.c_str(), aes_str.size(), aes_tmp_name, uint8_tab) ) + { + if( !uint8_tab.empty() ) + Ezc::UTF8ToWide((const char*)&uint8_tab[0], uint8_tab.size(), out); + + Clear(); + return true; + } + else + { + //log << "problem with AES decoding (skipping)" << logend; + } + + Clear(); + +return false; +} + + +bool Crypto::Decrypt(const std::string & in, std::vector & out) +{ + out.clear(); + + if( in.empty() ) + return true; + + base64.Decode(in, aes_str); + + if( aes.Decode((const unsigned char *)aes_str.c_str(), aes_str.size(), aes_tmp_name, uint8_tab) ) + { + out.resize(uint8_tab.size()); + + for(size_t i=0 ; i + */ + +/* + * Copyright (c) 2012, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef headerfile_tito_crypto +#define headerfile_tito_crypto + +#include "aes.h" +#include "base64.h" + + +namespace Tito +{ + + + +class Crypto +{ +public: + + + /* + setting AES256 key + the table should consists of 32 bytes + */ + bool SetAESKey(unsigned char aes_key[32]); + + + /* + crypting AES256 and base64 then + so the 'out' string is ready to save as a normal text + */ + void Crypt(const std::wstring & in, std::wstring & out); + void Crypt(const std::vector & in, std::string & out); + + + /* + decrypting base64 and AES256 then + decrypt can return false if the control sums are incorrect + in such a case out is empty + if 'in' is empty the 'out' will be empty too + */ + bool Decrypt(const std::wstring & in, std::wstring & out); + bool Decrypt(const std::string & in, std::vector & out); + + + /* + clearing a string or a vector + first it puts some characters and then calls clear() method + */ + template + void Clear(BufferType & str); + + +private: + + // AES cryptography + AES aes; + + // base64 encoding/decoding + Base64 base64; + + // a table used with AES + std::vector uint8_tab; + + // AES name (always empty) + std::string aes_name; + std::string aes_tmp_name; + + std::string utf8_str; + std::string base64_str; + std::string aes_str; + + void Clear(); + +}; + + + +template +void Crypto::Clear(BufferType & str) +{ + for(size_t i=0 ; i + */ + +/* + * Copyright (c) 2012, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "misc.h" + + +namespace Tito +{ + + + +void AssignString(const char * src, size_t len, std::wstring & dst, bool clear) +{ + if( clear ) + dst.clear(); + + if( dst.capacity() < dst.size() + len ) + dst.reserve(dst.size() + len + 128); + + for(size_t i=0 ; i(src[i]); +} + + + +void AssignString(const char * src, std::wstring & dst, bool clear) +{ +size_t len; + + for(len=0 ; src[len] ; ++len){} + + AssignString(src, len, dst, clear); +} + + +void AssignString(const std::string & src, std::wstring & dst, bool clear) +{ + AssignString(src.c_str(), src.size(), dst, clear); +} + + + + + +void AssignString(const wchar_t * src, size_t len, std::string & dst, bool clear) +{ + if( clear ) + dst.clear(); + + if( dst.capacity() < dst.size() + len ) + dst.reserve(dst.size() + len + 128); + + for(size_t i=0 ; i(src[i]); +} + + +void AssignString(const wchar_t * src, std::string & dst, bool clear) +{ +size_t len; + + for(len=0 ; src[len] ; ++len){} + + AssignString(src, len, dst, clear); +} + + +void AssignString(const std::wstring & src, std::string & dst, bool clear) +{ + AssignString(src.c_str(), src.size(), dst, clear); +} + + + +void AssignString(const char * src, size_t len, std::string & dst, bool clear) +{ + if( clear ) + dst.clear(); + + // we suppose that append is smart enough and we don't have to use reserve() + dst.append(src, len); +} + + + +void AssignString(const char * src, std::string & dst, bool clear) +{ +size_t len; + + for(len=0 ; src[len] ; ++len){} + + AssignString(src, len, dst, clear); +} + + + + +void AssignString(const std::string & src, std::string & dst, bool clear) +{ + if( clear ) + dst.clear(); + + dst.append(src); +} + + +void AssignString(const wchar_t * src, size_t len, std::wstring & dst, bool clear) +{ + if( clear ) + dst.clear(); + + // we suppose that append is smart enough and we don't have to use reserve() + dst.append(src, len); +} + + +void AssignString(const wchar_t * src, std::wstring & dst, bool clear) +{ +size_t len; + + for(len=0 ; src[len] ; ++len){} + + AssignString(src, len, dst, clear); +} + + + +void AssignString(const std::wstring & src, std::wstring & dst, bool clear) +{ + if( clear ) + dst.clear(); + + dst.append(src); +} + + + + +} // namespace Tito + + + + + + + diff --git a/misc.h b/misc.h new file mode 100755 index 0000000..6475f61 --- /dev/null +++ b/misc.h @@ -0,0 +1,83 @@ +/* + * This file is a part of Tito - a cryptography library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2012, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef headerfile_tito_misc +#define headerfile_tito_misc + + +#include +#include +#include +#include +#include + + +namespace Tito +{ + + + +/* + conversions between ascii text and wide characters + (destination is always std::string or std::wstring) + + characters are copied as they are without any locales checking +*/ + +void AssignString(const char * src, size_t len, std::wstring & dst, bool clear = true); +void AssignString(const char * src, std::wstring & dst, bool clear = true); +void AssignString(const std::string & src, std::wstring & dst, bool clear = true); + +void AssignString(const wchar_t * src, size_t len, std::string & dst, bool clear = true); +void AssignString(const wchar_t * src, std::string & dst, bool clear = true); +void AssignString(const std::wstring & src, std::string & dst, bool clear = true); + +void AssignString(const char * src, size_t len, std::string & dst, bool clear = true); +void AssignString(const char * src, std::string & dst, bool clear = true); +void AssignString(const std::string & src, std::string & dst, bool clear = true); + +void AssignString(const wchar_t * src, size_t len, std::wstring & dst, bool clear = true); +void AssignString(const wchar_t * src, std::wstring & dst, bool clear = true); +void AssignString(const std::wstring & src, std::wstring & dst, bool clear = true); + + + +} // namespace Tito + + + +#endif