broadfield-dev commited on
Commit
762b856
·
verified ·
1 Parent(s): d03e5ab

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +11 -22
app.py CHANGED
@@ -29,13 +29,7 @@ except FileNotFoundError:
29
  logger.error("FATAL: keylock_pub.pem not found.")
30
  PUBLIC_KEY_PEM_STRING = "Error: keylock_pub.pem file not found on the server."
31
 
32
- # --- Cryptographic Constants ---
33
- AES_KEY_SIZE_CRYPTO = 32
34
- AES_GCM_NONCE_SIZE_CRYPTO = 12
35
-
36
- # ==============================================================================
37
- # CORE DECRYPTION FUNCTION
38
- # ==============================================================================
39
  def decode_data(image_base64_string: str) -> dict:
40
  """
41
  This is the core logic function that will be exposed as an API.
@@ -43,15 +37,12 @@ def decode_data(image_base64_string: str) -> dict:
43
  """
44
  if not KEYLOCK_PRIV_KEY:
45
  raise gr.Error("Server Error: The API is not configured with a private key.")
46
-
47
  try:
48
- # 1. Decode base64 and load image
49
  image_buffer = base64.b64decode(image_base64_string)
50
  private_key = serialization.load_pem_private_key(KEYLOCK_PRIV_KEY.encode(), password=None)
51
  img = Image.open(io.BytesIO(image_buffer)).convert("RGB")
52
  pixel_data = np.array(img).ravel()
53
 
54
- # 2. Extract LSB data
55
  HEADER_BITS = 32
56
  if pixel_data.size < HEADER_BITS: raise ValueError("Image too small for header.")
57
  header_binary_string = "".join(str(pixel & 1) for pixel in pixel_data[:HEADER_BITS])
@@ -63,25 +54,22 @@ def decode_data(image_base64_string: str) -> dict:
63
  data_binary_string = "".join(str(pixel & 1) for pixel in pixel_data[HEADER_BITS:end_offset])
64
  crypto_payload = int(data_binary_string, 2).to_bytes(data_length, byteorder='big')
65
 
66
- # 3. Decrypt payload
67
  rsa_key_size_bytes = private_key.key_size // 8
68
  offset = 4
69
  encrypted_aes_key_len = struct.unpack('>I', crypto_payload[:offset])[0]
70
  if encrypted_aes_key_len != rsa_key_size_bytes: raise ValueError("Key pair mismatch.")
71
  encrypted_aes_key = crypto_payload[offset:offset + encrypted_aes_key_len]
72
  offset += encrypted_aes_key_len
73
- nonce = crypto_payload[offset:offset + AES_GCM_NONCE_SIZE_CRYPTO]
74
- offset += AES_GCM_NONCE_SIZE_CRYPTO
75
  ciphertext_with_tag = crypto_payload[offset:]
76
  recovered_aes_key = private_key.decrypt(
77
  encrypted_aes_key,
78
  padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)
79
  )
80
  decrypted_bytes = AESGCM(recovered_aes_key).decrypt(nonce, ciphertext_with_tag, None)
81
-
82
  logger.info("Successfully decoded an image.")
83
  return json.loads(decrypted_bytes.decode('utf-8'))
84
-
85
  except (ValueError, InvalidTag, TypeError) as e:
86
  logger.error(f"Decryption failed: {e}")
87
  raise gr.Error(f"Decryption failed. The image may be corrupt, or was not encrypted with the correct public key. Details: {e}")
@@ -94,7 +82,7 @@ def decode_data(image_base64_string: str) -> dict:
94
  # ==============================================================================
95
  with gr.Blocks(title="Secure Decoder API") as demo:
96
  gr.Markdown("# Secure KeyLock Decoder API (Server)")
97
- gr.Markdown("This Gradio Space provides the secure, server-side API for decoding KeyLock images. See documentation below.")
98
 
99
  with gr.Tabs():
100
  with gr.TabItem("API Status & Docs"):
@@ -105,23 +93,24 @@ with gr.Blocks(title="Secure Decoder API") as demo:
105
  gr.Markdown("---")
106
  gr.Markdown("## API Documentation")
107
  gr.Markdown("### Public Key\nUse the following public key to encrypt data for this service.")
108
- gr.Code(value=PUBLIC_KEY_PEM_STRING, language="python", label="Service Public Key")
109
 
110
- gr.Markdown("### API Endpoint: `/run/mcp_decode` (Base64)")
 
111
  gr.Markdown("- **Method**: `POST`\n- **Body**: `JSON`")
112
  gr.Code(language="json", label="JSON Payload Schema", value='{\n "data": [\n "iVBORw0KGgoAAAANSUhEUgA..."\n ]\n}')
113
- gr.Code(language="python", label="Example using cURL",
114
  value="""# Get base64 string: B64_STRING=$(base64 -w 0 /path/to/image.png)
115
  curl -X POST -H "Content-Type: application/json" \\
116
  -d '{"data": ["'$B64_STRING'"]}' \\
117
- https://your-space-name.hf.space/run/mcp_decode""")
118
 
119
  # --- This is the hidden component that creates the API endpoint ---
120
- # We define the function it calls (`decode_data`) and give it an `api_name`.
121
  with gr.Row(visible=False):
122
  api_input = gr.Textbox()
123
  api_output = gr.JSON()
124
- gr.Interface(fn=decode_data, inputs=api_input, outputs=api_output, api_name="mcp_decode")
 
125
 
126
  if __name__ == "__main__":
127
  demo.launch()
 
29
  logger.error("FATAL: keylock_pub.pem not found.")
30
  PUBLIC_KEY_PEM_STRING = "Error: keylock_pub.pem file not found on the server."
31
 
32
+ # --- Core Decryption Function ---
 
 
 
 
 
 
33
  def decode_data(image_base64_string: str) -> dict:
34
  """
35
  This is the core logic function that will be exposed as an API.
 
37
  """
38
  if not KEYLOCK_PRIV_KEY:
39
  raise gr.Error("Server Error: The API is not configured with a private key.")
 
40
  try:
 
41
  image_buffer = base64.b64decode(image_base64_string)
42
  private_key = serialization.load_pem_private_key(KEYLOCK_PRIV_KEY.encode(), password=None)
43
  img = Image.open(io.BytesIO(image_buffer)).convert("RGB")
44
  pixel_data = np.array(img).ravel()
45
 
 
46
  HEADER_BITS = 32
47
  if pixel_data.size < HEADER_BITS: raise ValueError("Image too small for header.")
48
  header_binary_string = "".join(str(pixel & 1) for pixel in pixel_data[:HEADER_BITS])
 
54
  data_binary_string = "".join(str(pixel & 1) for pixel in pixel_data[HEADER_BITS:end_offset])
55
  crypto_payload = int(data_binary_string, 2).to_bytes(data_length, byteorder='big')
56
 
 
57
  rsa_key_size_bytes = private_key.key_size // 8
58
  offset = 4
59
  encrypted_aes_key_len = struct.unpack('>I', crypto_payload[:offset])[0]
60
  if encrypted_aes_key_len != rsa_key_size_bytes: raise ValueError("Key pair mismatch.")
61
  encrypted_aes_key = crypto_payload[offset:offset + encrypted_aes_key_len]
62
  offset += encrypted_aes_key_len
63
+ nonce = crypto_payload[offset:offset + 12] # AES_GCM_NONCE_SIZE_CRYPTO
64
+ offset += 12
65
  ciphertext_with_tag = crypto_payload[offset:]
66
  recovered_aes_key = private_key.decrypt(
67
  encrypted_aes_key,
68
  padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)
69
  )
70
  decrypted_bytes = AESGCM(recovered_aes_key).decrypt(nonce, ciphertext_with_tag, None)
 
71
  logger.info("Successfully decoded an image.")
72
  return json.loads(decrypted_bytes.decode('utf-8'))
 
73
  except (ValueError, InvalidTag, TypeError) as e:
74
  logger.error(f"Decryption failed: {e}")
75
  raise gr.Error(f"Decryption failed. The image may be corrupt, or was not encrypted with the correct public key. Details: {e}")
 
82
  # ==============================================================================
83
  with gr.Blocks(title="Secure Decoder API") as demo:
84
  gr.Markdown("# Secure KeyLock Decoder API (Server)")
85
+ gr.Markdown("This Gradio Space provides the secure, server-side API for decoding KeyLock images.")
86
 
87
  with gr.Tabs():
88
  with gr.TabItem("API Status & Docs"):
 
93
  gr.Markdown("---")
94
  gr.Markdown("## API Documentation")
95
  gr.Markdown("### Public Key\nUse the following public key to encrypt data for this service.")
96
+ gr.Code(value=PUBLIC_KEY_PEM_STRING, language="pem", label="Service Public Key")
97
 
98
+ # --- UPDATED DOCUMENTATION TO REFLECT NEW API NAME ---
99
+ gr.Markdown("### API Endpoint: `/run/keylock-auth-decoder`")
100
  gr.Markdown("- **Method**: `POST`\n- **Body**: `JSON`")
101
  gr.Code(language="json", label="JSON Payload Schema", value='{\n "data": [\n "iVBORw0KGgoAAAANSUhEUgA..."\n ]\n}')
102
+ gr.Code(language="bash", label="Example using cURL",
103
  value="""# Get base64 string: B64_STRING=$(base64 -w 0 /path/to/image.png)
104
  curl -X POST -H "Content-Type: application/json" \\
105
  -d '{"data": ["'$B64_STRING'"]}' \\
106
+ https://your-space-name.hf.space/run/keylock-auth-decoder""")
107
 
108
  # --- This is the hidden component that creates the API endpoint ---
 
109
  with gr.Row(visible=False):
110
  api_input = gr.Textbox()
111
  api_output = gr.JSON()
112
+ # --- RENAMED API ENDPOINT AS REQUESTED ---
113
+ gr.Interface(fn=decode_data, inputs=api_input, outputs=api_output, api_name="keylock-auth-decoder")
114
 
115
  if __name__ == "__main__":
116
  demo.launch()