File: test_cipher.py

package info (click to toggle)
python-nss 0.15.0-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 1,452 kB
  • ctags: 1,755
  • sloc: ansic: 27,607; python: 2,688; makefile: 2
file content (170 lines) | stat: -rwxr-xr-x 6,260 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#!/usr/bin/python

import sys
import os
import unittest

import nss.nss as nss

#-------------------------------------------------------------------------------

verbose = False
mechanism = nss.CKM_DES_CBC_PAD
plain_text = "Encrypt me!"
key = "e8:a7:7c:e2:05:63:6a:31"
iv = "e4:bb:3b:d3:c3:71:2e:58"
in_filename = sys.argv[0]
chunk_size = 128

#-------------------------------------------------------------------------------

def setup_contexts(mechanism, key, iv):
    # Get a PK11 slot based on the cipher
    slot = nss.get_best_slot(mechanism)

    # If key was supplied use it, otherwise generate one
    if key:
        if verbose:
            print "using supplied key data"
            print "key:\n%s" % (key)
        key_si = nss.SecItem(nss.read_hex(key))
        sym_key = nss.import_sym_key(slot, mechanism, nss.PK11_OriginUnwrap,
                                     nss.CKA_ENCRYPT, key_si)
    else:
        if verbose:
            print "generating key data"
        sym_key = slot.key_gen(mechanism, None, slot.get_best_key_length(mechanism))

    # If initialization vector was supplied use it, otherwise set it to None
    if iv:
        if verbose:
            print "supplied iv:\n%s" % (iv)
        iv_data = nss.read_hex(iv)
        iv_si = nss.SecItem(iv_data)
        iv_param = nss.param_from_iv(mechanism, iv_si)
    else:
        iv_length = nss.get_iv_length(mechanism)
        if iv_length > 0:
            iv_data = nss.generate_random(iv_length)
            iv_si = nss.SecItem(iv_data)
            iv_param = nss.param_from_iv(mechanism, iv_si)
            if verbose:
                print "generated %d byte initialization vector: %s" % \
                    (iv_length, nss.data_to_hex(iv_data, separator=":"))
        else:
            iv_param = None

    # Create an encoding context
    encoding_ctx = nss.create_context_by_sym_key(mechanism, nss.CKA_ENCRYPT,
                                                 sym_key, iv_param)

    # Create a decoding context
    decoding_ctx = nss.create_context_by_sym_key(mechanism, nss.CKA_DECRYPT,
                                                 sym_key, iv_param)

    return encoding_ctx, decoding_ctx

#-------------------------------------------------------------------------------

class TestCipher(unittest.TestCase):
    def setUp(self):
        nss.nss_init_nodb()
        self.encoding_ctx, self.decoding_ctx = setup_contexts(mechanism, key, iv)

    def tearDown(self):
        del self.encoding_ctx
        del self.decoding_ctx
        nss.nss_shutdown()

    def test_string(self):
        if verbose:
            print "Plain Text:\n%s" % (plain_text)

        # Encode the plain text by feeding it to cipher_op getting cipher text back.
        # Append the final bit of cipher text by calling digest_final
        cipher_text = self.encoding_ctx.cipher_op(plain_text)
        cipher_text += self.encoding_ctx.digest_final()

        if verbose:
            print "Cipher Text:\n%s" % (nss.data_to_hex(cipher_text, separator=":"))

        # Decode the cipher text by feeding it to cipher_op getting plain text back.
        # Append the final bit of plain text by calling digest_final
        decoded_text = self.decoding_ctx.cipher_op(cipher_text)
        decoded_text += self.decoding_ctx.digest_final()

        if verbose:
            print "Decoded Text:\n%s" % (decoded_text)

        # Validate the encryption/decryption by comparing the decoded text with
        # the original plain text, they should match.
        self.assertEqual(decoded_text, plain_text)

        self.assertNotEqual(cipher_text, plain_text)

    def test_file(self):
        encrypted_filename = os.path.basename(in_filename) + ".encrypted"
        decrypted_filename = os.path.basename(in_filename) + ".decrypted"

        in_file = open(in_filename, "r")
        encrypted_file = open(encrypted_filename, "w")

        if verbose:
            print "Encrypting file \"%s\" to \"%s\"" % (in_filename, encrypted_filename)

        # Encode the data read from a file in chunks
        while True:
            # Read a chunk of data until EOF, encrypt it and write the encrypted data
            in_data = in_file.read(chunk_size)
            if len(in_data) == 0:   # EOF
                break
            encrypted_data = self.encoding_ctx.cipher_op(in_data)
            encrypted_file.write(encrypted_data)
        # Done encoding the input, get the final encoded data, write it, close files
        encrypted_data = self.encoding_ctx.digest_final()
        encrypted_file.write(encrypted_data)
        in_file.close()
        encrypted_file.close()

        # Decode the encoded file in a similar fashion
        if verbose:
            print "Decrypting file \"%s\" to \"%s\"" % (encrypted_filename, decrypted_filename)

        encrypted_file = open(encrypted_filename, "r")
        decrypted_file = open(decrypted_filename, "w")
        while True:
            # Read a chunk of data until EOF, encrypt it and write the encrypted data
            in_data = encrypted_file.read(chunk_size)
            if len(in_data) == 0:   # EOF
                break
            decrypted_data = self.decoding_ctx.cipher_op(in_data)
            decrypted_file.write(decrypted_data)
        # Done encoding the input, get the final encoded data, write it, close files
        decrypted_data = self.decoding_ctx.digest_final()
        decrypted_file.write(decrypted_data)
        encrypted_file.close()
        decrypted_file.close()

        # Validate the encryption/decryption by comparing the decoded text with
        # the original plain text, they should match.
        in_data        = open(in_filename).read()
        encrypted_data = open(encrypted_filename).read()
        decrypted_data = open(decrypted_filename).read()
        if decrypted_data != in_data:
            result = 1
            print "FAILED! decrypted_data != in_data"

        if encrypted_data == in_data:
            result = 1
            print "FAILED! encrypted_data == in_data"

        # clean up
        os.unlink(encrypted_filename)
        os.unlink(decrypted_filename)



#-------------------------------------------------------------------------------

if __name__ == '__main__':
    unittest.main()