1 /*
2 * Adding an application specific engine
3 * (C) 2004,2008 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #include <botan/stream_cipher.h>
9 #include <botan/engine.h>
10 
11 using namespace Botan;
12 
13 class XOR_Cipher : public StreamCipher
14    {
15    public:
clear()16       void clear() throw() { mask.clear(); mask_pos = 0; }
17 
18       // what we want to call this cipher
name() const19       std::string name() const { return "XOR"; }
20 
21       // return a new object of this type
clone() const22       StreamCipher* clone() const { return new XOR_Cipher; }
23 
key_spec() const24       Key_Length_Specification key_spec() const
25          {
26          return Key_Length_Specification(1, 32);
27          }
28 
XOR_Cipher()29       XOR_Cipher() : mask_pos(0) {}
30    private:
cipher(const byte in[],byte out[],size_t length)31       void cipher(const byte in[], byte out[], size_t length)
32          {
33          for(size_t j = 0; j != length; j++)
34             {
35             out[j] = in[j] ^ mask[mask_pos];
36             mask_pos = (mask_pos + 1) % mask.size();
37             }
38          }
39 
key_schedule(const byte key[],size_t length)40       void key_schedule(const byte key[], size_t length)
41          {
42          mask.resize(length);
43          copy_mem(&mask[0], key, length);
44          }
45 
46       SecureVector<byte> mask;
47       u32bit mask_pos;
48    };
49 
50 class Application_Engine : public Engine
51    {
52    public:
provider_name() const53       std::string provider_name() const { return "application"; }
54 
find_stream_cipher(const SCAN_Name & request,Algorithm_Factory &) const55       StreamCipher* find_stream_cipher(const SCAN_Name& request,
56                                        Algorithm_Factory&) const
57          {
58          if(request.algo_name() == "XOR")
59             return new XOR_Cipher;
60          return 0;
61          }
62    };
63 
64 #include <botan/botan.h>
65 #include <iostream>
66 #include <string>
67 
main()68 int main()
69    {
70 
71    Botan::LibraryInitializer init;
72 
73    global_state().algorithm_factory().add_engine(
74       new Application_Engine);
75 
76    // a hex key value
77    SymmetricKey key("010203040506070809101112AAFF");
78 
79    /*
80     Since stream ciphers are typically additive, the encryption and
81     decryption ops are the same, so this isn't terribly interesting.
82 
83     If this where a block cipher you would have to add a cipher mode and
84     padding method, such as "/CBC/PKCS7".
85    */
86    Pipe enc(get_cipher("XOR", key, ENCRYPTION), new Hex_Encoder);
87    Pipe dec(new Hex_Decoder, get_cipher("XOR", key, DECRYPTION));
88 
89    // I think the pigeons are actually asleep at midnight...
90    std::string secret = "The pigeon flys at midnight.";
91 
92    std::cout << "The secret message is '" << secret << "'" << std::endl;
93 
94    enc.process_msg(secret);
95    std::string cipher = enc.read_all_as_string();
96 
97    std::cout << "The encrypted secret message is " << cipher << std::endl;
98 
99    dec.process_msg(cipher);
100    secret = dec.read_all_as_string();
101 
102    std::cout << "The decrypted secret message is '"
103              << secret << "'" << std::endl;
104 
105    return 0;
106    }
107