updates
Browse files- Dockerfile +3 -0
- main.py +7 -0
- scripts/upload.sh +26 -0
- scripts/verify.sh +165 -0
Dockerfile
CHANGED
@@ -36,6 +36,9 @@ RUN unzip truepic-lens-cli-51f4cfbc6472a2205e53d726713619ca8df5340b-ubuntu-20.04
|
|
36 |
RUN tar -xf truepic-lens-cli-51f4cfbc6472a2205e53d726713619ca8df5340b-ubuntu-20.04.tar.gz
|
37 |
|
38 |
RUN chmod +x truepic
|
|
|
|
|
|
|
39 |
|
40 |
RUN --mount=type=secret,id=api_key,mode=0444,required=true \
|
41 |
./truepic enroll file-system --api-key $(cat /run/secrets/api_key)
|
|
|
36 |
RUN tar -xf truepic-lens-cli-51f4cfbc6472a2205e53d726713619ca8df5340b-ubuntu-20.04.tar.gz
|
37 |
|
38 |
RUN chmod +x truepic
|
39 |
+
RUN chmod +x scripts/sign.sh
|
40 |
+
RUN chmod +x scripts/verify.sh
|
41 |
+
RUN chmod +x scripts/upload.sh
|
42 |
|
43 |
RUN --mount=type=secret,id=api_key,mode=0444,required=true \
|
44 |
./truepic enroll file-system --api-key $(cat /run/secrets/api_key)
|
main.py
CHANGED
@@ -91,6 +91,13 @@ def verify_image(fileUpload: UploadFile):
|
|
91 |
# ]
|
92 |
# )
|
93 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
subprocess.check_output(
|
95 |
[
|
96 |
"./scripts/sign.sh",
|
|
|
91 |
# ]
|
92 |
# )
|
93 |
|
94 |
+
subprocess.check_output(
|
95 |
+
[
|
96 |
+
"export",
|
97 |
+
"STEG_AI_API_KEY=" + os.environ.get("steg_api_key"),
|
98 |
+
]
|
99 |
+
)
|
100 |
+
|
101 |
subprocess.check_output(
|
102 |
[
|
103 |
"./scripts/sign.sh",
|
scripts/upload.sh
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env bash
|
2 |
+
|
3 |
+
set -e
|
4 |
+
|
5 |
+
FILE=$(readlink -f "$1")
|
6 |
+
FORMAT=$2
|
7 |
+
|
8 |
+
json_data=$(
|
9 |
+
curl -s https://api.steg.ai/upload \
|
10 |
+
-H "x-api-key: ${STEG_AI_API_KEY}" \
|
11 |
+
--data-raw '{ "name": "'$(basename "${FILE}")'", "content_type": "'$FORMAT'" }')
|
12 |
+
|
13 |
+
readarray -t fields < <(echo "${json_data}" | jq -r '.data.post_to.fields | keys[]')
|
14 |
+
media_id=$(echo "${json_data}" | jq -r '.data.media_id')
|
15 |
+
presigned_url=$(echo "${json_data}" | jq -r '.data.post_to.url')
|
16 |
+
|
17 |
+
# Iterate over the keys array and build the curl parameters
|
18 |
+
form_string=""
|
19 |
+
for field in "${fields[@]}"; do
|
20 |
+
value=$(echo "${json_data}" | jq -r --arg key "${field}" '.data.post_to.fields[$key]')
|
21 |
+
form_string+="--form ${field}=${value} "
|
22 |
+
done
|
23 |
+
|
24 |
+
curl -s --location --request POST ${presigned_url} ${form_string} --form "file=@${FILE}"
|
25 |
+
|
26 |
+
echo ${media_id}
|
scripts/verify.sh
ADDED
@@ -0,0 +1,165 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env bash
|
2 |
+
|
3 |
+
set -e
|
4 |
+
|
5 |
+
MEDIA_FILE=$(readlink -f "$1")
|
6 |
+
|
7 |
+
TRUEPIC_CLI=/home/user/app/truepic
|
8 |
+
STEG_SCRIPTS=/home/user/app/scripts/
|
9 |
+
|
10 |
+
echo -n "Checking for C2PA data in the media..."
|
11 |
+
set +e
|
12 |
+
verification_json=$(${TRUEPIC_CLI} verify $MEDIA_FILE 2>&1)
|
13 |
+
set -e
|
14 |
+
|
15 |
+
if jq -e . <<< "$verification_json" >/dev/null 2>&1; then
|
16 |
+
echo " embedded C2PA manifest found."
|
17 |
+
echo
|
18 |
+
echo ${verification_json} | jq
|
19 |
+
exit 0
|
20 |
+
fi
|
21 |
+
echo " no embedded C2PA manifest found."
|
22 |
+
|
23 |
+
echo
|
24 |
+
echo -n "Uploading media to steg.ai..."
|
25 |
+
media_id=$(${STEG_SCRIPTS}/upload.sh ${MEDIA_FILE} "image/jpeg")
|
26 |
+
echo " --> media_id=${media_id}"
|
27 |
+
|
28 |
+
echo
|
29 |
+
echo -n "Detecting a watermark..."
|
30 |
+
decode_response=$(
|
31 |
+
curl -s https://api.steg.ai/decode_image_async \
|
32 |
+
-H "x-api-key: ${STEG_AI_API_KEY}" \
|
33 |
+
--data-raw '{ "media_id": "'${media_id}'" }'
|
34 |
+
)
|
35 |
+
request_id=$(echo "$decode_response" | jq -r '.data.request_id')
|
36 |
+
|
37 |
+
if [ -z "$request_id" ] || [ "$request_id" = "null" ]; then
|
38 |
+
echo
|
39 |
+
echo "No request_id"
|
40 |
+
exit 1;
|
41 |
+
fi
|
42 |
+
|
43 |
+
status_response=""
|
44 |
+
decode_status=""
|
45 |
+
while [ "$decode_status" != "Completed." ]; do
|
46 |
+
sleep 1
|
47 |
+
echo -n ".."
|
48 |
+
status_response=$(
|
49 |
+
curl -s https://api.steg.ai/media_status?request_id=${request_id} \
|
50 |
+
-H "x-api-key: ${STEG_AI_API_KEY}"
|
51 |
+
)
|
52 |
+
decode_status=$(echo "${status_response}" | jq -r '.data.status')
|
53 |
+
done
|
54 |
+
|
55 |
+
manifest_id=$(echo "${status_response}" | jq -r '.data.media_data.custom' | jq -r '.manifest_id')
|
56 |
+
watermark_signature=$(echo "${status_response}" | jq -r '.data.media_data.custom' | jq -r '.watermark_signature')
|
57 |
+
|
58 |
+
if [ -z "$manifest_id" ] || [ "$manifest_id" = "null" ]; then
|
59 |
+
echo
|
60 |
+
echo "No manifest_id"
|
61 |
+
else
|
62 |
+
echo " --> media_id=${manifest_id}"
|
63 |
+
fi
|
64 |
+
|
65 |
+
echo
|
66 |
+
echo -n "Deleting uploaded media (${media_id}) from steg.ai... "
|
67 |
+
delete_result=$(
|
68 |
+
curl -s https://api.steg.ai/asset \
|
69 |
+
-X DELETE \
|
70 |
+
-H "x-api-key: ${STEG_AI_API_KEY}" \
|
71 |
+
--data-raw '{
|
72 |
+
"media_id" : "'${media_id}'"
|
73 |
+
}'
|
74 |
+
)
|
75 |
+
|
76 |
+
if [ -z "$manifest_id" ] || [ "$manifest_id" = "null" ]; then
|
77 |
+
exit 1
|
78 |
+
fi
|
79 |
+
|
80 |
+
echo ${delete_result} | jq -r '.message'
|
81 |
+
echo
|
82 |
+
echo -n "Downloading manifest..."
|
83 |
+
manifest_info=$(curl -s https://api.steg.ai/asset?media_id=${manifest_id} -H "x-api-key: ${STEG_AI_API_KEY}")
|
84 |
+
manifest_url=$(echo ${manifest_info} | jq -r '.data[0].path')
|
85 |
+
downloaded_manifest=$(mktemp).bin
|
86 |
+
curl -s -o ${downloaded_manifest} ${manifest_url}
|
87 |
+
echo " --> ${downloaded_manifest}"
|
88 |
+
|
89 |
+
echo
|
90 |
+
echo -n "Inserting manifest into media file..."
|
91 |
+
${TRUEPIC_CLI} manifest insert ${downloaded_manifest} $MEDIA_FILE --output re_inserted_image.jpg > /dev/null 2>&1
|
92 |
+
echo " --> re_inserted_image.jpg"
|
93 |
+
|
94 |
+
echo
|
95 |
+
echo "Checking the manifest."
|
96 |
+
verification_json=$(${TRUEPIC_CLI} verify re_inserted_image.jpg)
|
97 |
+
|
98 |
+
hash_status=$(
|
99 |
+
echo "${verification_json}" | \
|
100 |
+
jq -r '.manifest_store[] | select(.is_active == true) | .assertions."c2pa.hash.data"[0].status'
|
101 |
+
)
|
102 |
+
thumbnail_hash=$(
|
103 |
+
echo "${verification_json}" | \
|
104 |
+
jq -r '.manifest_store[0].assertions."c2pa.thumbnail.claim.jpeg"[0].thumbnail_id'
|
105 |
+
)
|
106 |
+
timestamp=$(
|
107 |
+
echo "${verification_json}" | \
|
108 |
+
jq -r '.manifest_store[0].trusted_timestamp.timestamp'
|
109 |
+
)
|
110 |
+
public_key=$(
|
111 |
+
echo "${verification_json}" | \
|
112 |
+
jq -r '.manifest_store[] | select(.is_active == true) | .certificate.cert_der' | \
|
113 |
+
base64 -d | \
|
114 |
+
openssl x509 -pubkey -noout
|
115 |
+
)
|
116 |
+
|
117 |
+
echo -n "Checking watermark signature... ${thumbnail_hash}|${timestamp} ... ${watermark_signature} ..."
|
118 |
+
signature_verification=$(
|
119 |
+
openssl dgst -sha256 \
|
120 |
+
-verify <(echo "${public_key}") \
|
121 |
+
-signature <(echo "${watermark_signature}" | base64 -d) \
|
122 |
+
<(echo "${thumbnail_hash}|${timestamp}")
|
123 |
+
)
|
124 |
+
|
125 |
+
echo " ${signature_verification}"
|
126 |
+
|
127 |
+
echo -n "Checking image hash..."
|
128 |
+
if [ "$hash_status" = "VALID" ]; then
|
129 |
+
echo " hashes match."
|
130 |
+
echo "${verification_json}" | jq
|
131 |
+
rm -f ${downloaded_manifest}
|
132 |
+
exit 0
|
133 |
+
fi
|
134 |
+
echo " hashes DON'T match!"
|
135 |
+
rm -f re_inserted_image.jpg
|
136 |
+
|
137 |
+
echo
|
138 |
+
echo -n "Re-signing the watermarked media..."
|
139 |
+
${TRUEPIC_CLI} sign ${MEDIA_FILE} \
|
140 |
+
--ingredient-manifest-store ${downloaded_manifest} \
|
141 |
+
--output re_signed_image.jpg \
|
142 |
+
--assertions-inline '{
|
143 |
+
"assertions": [
|
144 |
+
{
|
145 |
+
"label": "c2pa.actions",
|
146 |
+
"data": {
|
147 |
+
"actions": [
|
148 |
+
{
|
149 |
+
"action": "c2pa.unknown",
|
150 |
+
"when": "@now",
|
151 |
+
"parameters": {
|
152 |
+
"description": "Some unknown edits have been made between watermarking and now."
|
153 |
+
}
|
154 |
+
}
|
155 |
+
]
|
156 |
+
}
|
157 |
+
}
|
158 |
+
]
|
159 |
+
}' > /dev/null 2>&1
|
160 |
+
echo " --> re_signed_image.jpg"
|
161 |
+
rm -f ${downloaded_manifest}
|
162 |
+
|
163 |
+
echo
|
164 |
+
echo "Checking the manifest..."
|
165 |
+
${TRUEPIC_CLI} verify re_signed_image.jpg | jq
|