File size: 6,531 Bytes
f47979d
36e3dbb
 
f47979d
8fdc28e
3032f7f
f47979d
4d8e57a
 
 
 
 
3032f7f
4d8e57a
 
f47979d
36e3dbb
 
 
 
 
 
 
 
 
 
 
 
3032f7f
 
 
 
 
 
 
 
 
 
 
 
 
 
36e3dbb
 
 
3032f7f
 
36e3dbb
3032f7f
 
36e3dbb
 
3032f7f
 
 
 
 
 
 
 
 
 
 
36e3dbb
effe5ca
 
 
 
 
 
 
ddb5d02
effe5ca
 
 
 
 
 
 
 
 
ddb5d02
effe5ca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36e3dbb
f47979d
3032f7f
effe5ca
f47979d
 
 
ddb5d02
 
 
 
 
 
 
36e3dbb
f47979d
4d8e57a
 
 
f47979d
36e3dbb
 
f47979d
4d8e57a
 
 
f47979d
36e3dbb
 
ddb5d02
f47979d
8fdc28e
ddb5d02
 
 
 
 
 
 
8fdc28e
 
 
ddb5d02
 
 
 
 
8fdc28e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f47979d
ddb5d02
effe5ca
ddb5d02
 
 
 
 
 
 
 
 
 
 
 
 
effe5ca
f47979d
 
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
171
172
173
174
175
176
177
178
179
from PIL import Image
import numpy as np
import streamlit as st
import io
import time
import random

# Resize image to prevent memory issues with large images
def resize_image(img, max_size=(3000, 3000)):
    """
    Resize image to fit within max_size while maintaining aspect ratio.
    """
    img.thumbnail(max_size, Image.Resampling.LANCZOS)
    return img

# Logistic map function
def logistic_map(r, x):
    return r * x * (1 - x)

# Generate chaotic key based on the logistic map
def generate_key(seed, n):
    key = []
    x = seed
    for _ in range(n):
        x = logistic_map(3.9, x)
        key.append(int(x * 255) % 256)  # Map to 0-255
    return np.array(key, dtype=np.uint8)

# Shuffle pixels using a chaotic sequence
def shuffle_pixels(img_array, seed):
    h, w, c = img_array.shape
    num_pixels = h * w
    flattened = img_array.reshape(-1, c)
    indices = np.arange(num_pixels)
    
    random.seed(seed)
    random.shuffle(indices)  # Shuffle indices
    
    shuffled = flattened[indices]
    return shuffled.reshape(h, w, c), indices

# Multi-layer encryption using logistic map and pixel shuffling
def encrypt_image(img_array, seed):
    h, w, c = img_array.shape
    flat_image = img_array.flatten()

    # Generate chaotic key
    chaotic_key = generate_key(seed, len(flat_image))
    
    # XOR-based encryption
    encrypted_flat = [pixel ^ chaotic_key[i] for i, pixel in enumerate(flat_image)]
    encrypted_array = np.array(encrypted_flat, dtype=np.uint8).reshape(h, w, c)

    # Pixel shuffling
    shuffled_array, indices = shuffle_pixels(encrypted_array, seed)

    # Second layer of logistic map encryption
    chaotic_key_2 = generate_key(seed * 1.1, len(flat_image))
    shuffled_flat = shuffled_array.flatten()
    doubly_encrypted_flat = [pixel ^ chaotic_key_2[i] for i, pixel in enumerate(shuffled_flat)]
    doubly_encrypted_array = np.array(doubly_encrypted_flat, dtype=np.uint8).reshape(h, w, c)

    return doubly_encrypted_array

# Decrypt function
def decrypt_image(encrypted_array, seed, original_shape):
    h, w, c = original_shape
    flat_image = encrypted_array.flatten()

    # Generate the second chaotic key
    chaotic_key_2 = generate_key(seed * 1.1, len(flat_image))

    # Reverse the second XOR encryption
    xor_reversed_flat = [pixel ^ chaotic_key_2[i] for i, pixel in enumerate(flat_image)]
    xor_reversed_array = np.array(xor_reversed_flat, dtype=np.uint8).reshape(h, w, c)

    # Reverse pixel shuffling
    shuffled_array = xor_reversed_array
    num_pixels = h * w
    flattened = shuffled_array.reshape(-1, c)
    indices = np.arange(num_pixels)

    random.seed(seed)
    random.shuffle(indices)  # Reuse the same shuffle logic
    unshuffled = np.zeros_like(flattened)
    unshuffled[indices] = flattened
    unshuffled_array = unshuffled.reshape(h, w, c)

    # Generate the first chaotic key
    chaotic_key_1 = generate_key(seed, len(flat_image))

    # Reverse the first XOR encryption
    decrypted_flat = [pixel ^ chaotic_key_1[i] for i, pixel in enumerate(unshuffled_array.flatten())]
    decrypted_array = np.array(decrypted_flat, dtype=np.uint8).reshape(h, w, c)

    return decrypted_array

# Streamlit App
def main():
    st.title("Enhanced Chaotic Logistic Map Image Encryption")
    st.write("Upload an image to encrypt and decrypt using advanced chaotic logistic map methods.")

    uploaded_file = st.file_uploader("Upload an image", type=["jpg", "jpeg", "png"])
    if uploaded_file is not None:
        with st.spinner("Processing upload..."):
            # Simulate a loading delay for upload progress
            progress_bar = st.progress(0)
            for percent_complete in range(0, 101, 20):
                time.sleep(0.1)  # Simulate progress
                progress_bar.progress(percent_complete)

        # Load the uploaded image
        input_image = Image.open(uploaded_file)

        # Resize the image if necessary
        input_image = resize_image(input_image)

        # Display original image
        st.image(input_image, caption="Uploaded Image", use_container_width=True)

        # Convert image to numpy array
        img_array = np.array(input_image)

        # Key input
        key_seed = st.slider("Set the encryption key seed (0 < key < 1)", min_value=0.001, max_value=0.999, step=0.001)

        # Encrypt Image
        if st.button("Encrypt Image"):
            with st.spinner("Encrypting image..."):
                # Simulate a loading delay for encryption progress
                progress_bar = st.progress(0)
                for percent_complete in range(0, 101, 20):
                    time.sleep(0.1)  # Simulate progress
                    progress_bar.progress(percent_complete)

                # Encrypt the image
                encrypted_array = encrypt_image(img_array, key_seed)
                encrypted_image = Image.fromarray(encrypted_array)

                # Store encrypted array in session state
                st.session_state["encrypted_array"] = encrypted_array
                st.session_state["original_shape"] = img_array.shape
                st.session_state["key_seed"] = key_seed

                # Display encrypted image
                st.image(encrypted_image, caption="Encrypted Image", use_container_width=True)

                # Save encrypted image to a buffer
                buffer = io.BytesIO()
                encrypted_image.save(buffer, format="PNG")
                buffer.seek(0)

                # Download button for encrypted image
                st.download_button(
                    label="Download Encrypted Image",
                    data=buffer,
                    file_name="encrypted_image.png",
                    mime="image/png"
                )

        # Decrypt Image
        if st.button("Decrypt Image"):
            if "encrypted_array" in st.session_state:
                with st.spinner("Decrypting image..."):
                    decrypted_array = decrypt_image(
                        st.session_state["encrypted_array"],
                        st.session_state["key_seed"],
                        st.session_state["original_shape"]
                    )
                    decrypted_image = Image.fromarray(decrypted_array)

                    # Display decrypted image
                    st.image(decrypted_image, caption="Decrypted Image", use_container_width=True)
            else:
                st.error("No encrypted image found. Please encrypt an image first.")

if __name__ == "__main__":
    main()