نبذة عن علم إخفاء البيانات وتطبيق خوارزمية LSB باستخدام PHP
نبذة عن علم إخفاء البيانات Steganography وتطبيق خوارزمية LSB باستخدام PHP لإخفاء نص بداخل صورة.
مقدمة
كلمة Steganography هي كلمة تعني اخفاء البيانات أو النصوص، وتهدف إلى إخفاء البيانات دون إثارة الشكوك حولها بكونها تحتوي على رسالة أو ملف مخفي، وهي تختلف عن علم التشفير (Cryptography)، وللتبسيط، يمكنك تشبيه التشفير بخزنة تضع بداخلها البيانات، ولا يمكن فتح الخزنة إلا بمفتاح معين، بينما إخفاء البيانات عبارة عن تمويه فقط للبيانات، ككتابة رسالة معينة، لو جمعت أول حرف من كل كلمة فيها تجد رسالة أخرى مثلا.
وهذه قد تعد ميزة لإخفاء البيانات، فهي لا تثير الشك بوجود بيانات مخفية، على عكس التشفير، فناتج التشفير يكون مختلفا تماما وغير مقروء أو مفهوم، مما قد يثير الشكوك حوله، توجد أدوات جاهزة تقوم بعملية اخفاء البيانات، منها مثل أداة Steghide، لكن كمبرمجين، سنتعرف على طريقة عمل مثل هذه الأدوات.
هناك عدد من الطرق والخوارزميات لإخفاء البيانات، حيث بإمكانك اخفاء نوع من البيانات ( كالنصوص والملفات ) داخل نوع آخر من البيانات، فمثلا بإمكانك اخفاء صورة بداخل صورة أخرى، أو صورة بداخل ملف فيديو، أو نص بداخل ملف صوتي، وهكذا، دون أن يلاحظ من يشاهد الصورة بتغيير فيها، فالخوارزميات المختصة بإخفاء البيانات تتلاعب بمحتويات الملف، حيث تعدل الـ bits الخاصة بالملف وتتلاعب به بحيث لا تؤثر على محتويات الملف، وبنفس الوقت تحقن بداخله الـ bits الخاصة بالملف الآخر، فعندما ترى صورة تحتوي بداخلها على نص مثلا، فإنك لن ترى النص، فالنص يُمثل داخل الصورة على شكل bits، ولن تلاحظ كذلك تغيرا على جودة الصورة ( بحسب الطريقة المستخدمة طبعا ).
وفي هذا الشرح، سنتطرق أولا إلى احدى الخوارزميات المعروفة لاخفاء البيانات، وستفهم الموضوع أكثر بفهم الخوارزمية، وبعدها سنقوم بكتابة كود الخوارزمية باستخدام لغة PHP.
مفاهيم نظرية مهمة قبل البدء
ان كل البيانات المخزنة داخل الحاسوب هي في الأساس تمثل بنظام العد الثنائي binary، وقد سمي نظام العد الثنائي بهذا الاسم، لاحتوائه فقط على رقمين ( رمزين ) لتمثيل البيانات، وهما 0 و 1، ولعرض بيانات يفهمها المستخدم ( كالنصوص والصور والأرقام ) يتم تحويل نظام Binary إلى أنظمة عد أخرى لتسهيل تمثيل البيانات، وسنتطرق في هذه المقدمة بشكل غير مفصل لطريقة تحويل نظام العد Binary إلى نظام العد Decimal ( الارقام التي نستخدمها في الحياة اليومية )، من ثم سنقوم بتوضيح طريقة تمثيل الصور في الحاسوب باستخدام نظام العد Binary وذلك لأننا سنستخدم الصور كمثال لاخفاء البيانات بداخلها.
نظام العد العشري Decimal هو نظام العد الذي يمثل الأرقام العادية التي نستخدمها في الحياة اليومية، وسمي بالعشري لامكانية تمثيله بعشرة أرقام، وهي الأرقام من 0 إلى 9.
لنفترض أن لدينا بايت واحد من البيانات ( والذي يساوي 8 bit )، لو تخيلنا شكله، فسيكون كالآتي:
لتمثيل أي رقم Decimal بنظام Binary، نقوم أولا بترقيم كل bit من اليمين إلى اليسار بـ ( 2^x )حيث x هو رقم الـ bit ابتداء من 0 ووصولا إلى n ( حيث n هو عدد ال bits الاجمالي ناقص واحد، وهو في هذه الحالة 7 )، فمثلا، البت الاول من اليمين يمثل بالرقم ( 1 = 0^2) والثاني ( 4 = 2^2) وهكذا، فيصبح الترقيم كالآتي:
والآن يتم تمثيل أي رقم بجعل قيم الـ bits التي مجموع ترقيمها يساوي الرقم الذي نريده، فالرقم 16 مثلا يُمثل بهذه الطريقة:
وهذا مثال على الرقم 137 (128+8+1):
ومن الطريقة السابقة، نلاحظ أن أقصى قيمة عددية يمكن أن يمثلها البايت الواحد هي 255 ( وهي ناتج جمع كل الأرقام السابقة 128+64+32+16+8+4+2+1 )، ولتمثيل أعداد أكبر تحتاج إلى المزيد من البايتات.
يفترض أن أغلب المبرمجين يعرفون المعلومات السابقة، لكن كيف يفيدنا هذا في موضوعنا ؟
كما ذكرنا في المقدمة، فإن خوارزميات إخفاء البيانات، تعتمد بشكل أساسي على التلاعب بالـ bits، لذلك لابد من فهم هذه المقدمة قبل شرح خوارزميات اخفاء البيانات، وبما أن مثالنا سيكون عن إخفاء نص بداخل صورة، فإن علينا أن نعرف كيف يتم تمثيل الصورة باستخدام نظام العد الثنائي.
مم تتكون الصور؟
تتكون الصور من مجموعة كبيرة من النقاط يسمى الواحد منها Pixel، وكل بكسل يحتوي لون واحد فقط، بالتالي فإننا عندما نتكلم عن طريقة "تمثيل الصور" نتكلم فعليا عن طريقة تمثيل كل بكسل داخل الصورة، لذلك بامكانك تشبيه الصورة بـ Matrix ( مصفوفة ثنائية البعد ) ويحتوي كل عنصر في هذه المصفوفة على بكسل واحد فقط، تختلف طريقة تمثيل البكسل بحسب عمق الألوان ووجود شفافية في الصورة من عدمه، لكن بشكل عام، نستطيع أن نقول أن اللون يتكون من تداخل قيم ثلاثة ألوان، وهي الأحمر والأخضر والأزرق (RGB)، وقيمة كل لون من هذه الألوان تُمثل باستخدام رقم من 0 إلى 255 وهو الرقم الذي يحدد كثافة اللون، ومما سبق معرفته عن طريقة تمثيل أرقام Decimal باستخدام Binary، نعلم أن الرقم 255 هو (11111111) في نظام Binary، أي أننا سنكون بحاجة لبايت واحد فقط لتمثيل اللون، وعلى افتراض ان البكسل فيه 3 قنوات فقط دون قناة الشفافية الموجودة في بعض صيغ الصور كـ PNG مثلا، فإننا سنمثل البكسل باستخدام 3 Bytes حيث يُمثل كل لون في بايت واحد.
هذا مثال على أحد الألوان وتمثيله باستخدام BInary:
ما هي خوارزمية LSB وكيف تعمل
Least Significant Bit (LSB) تعني بالعربية الـ Bit الأقل تأثيرا، لكن ما هو الـ Bit الأقل تأثيرا ؟
ربما لاحظت في الأمثلة السابقة أنك لو قرأت الـ Bits من اليمين إلى اليسار، فالقيمة العددية التي يمثلها الـ Bit تزداد، فالـ Bit الأول من اليمين يمثل لنا الرقم 1، بينما يمثل الأخير الرقم 128، لذلك فإننا كلما تحركنا إلى اليمين تقل القيمة العددية التي يمثلها الـ Bit ( ويقل تأثيره على البيانات )، فمثلا لو كان لدينا صورة وعكسنا قيمة الـ Bit الأول من اليمين لأحد البكسلات ( أو حتى لجميعها ) ففعليا لن تلاحظ فرقا كبيرا، فلو كانت كثافة اللون الأحمر في ذلك البكسل 127، فستصبح القيمة 126 بعد تغيير الـ Bit الأول من 1 إلى 0، والعين البشرية لن تلاحظ التغيير، فهو تغيير طفيف جدا، لذلك يسمى الـ Bit الأقل تأثيرا، فكلما تحركنا إلى اليمين قلت أهمية الـ Bit، في الصورة السابقة شاهدنا لونا ومثلناه باستخدام Binary، الصورة التالية ستعرض نفس اللون بعد تغيير أول Bit من كل لون، إضافة إلى عرض اللون القديم لتقارن بينهما:
من الواضح جدا عدم وجود فرق وعدم إمكانية التمييز بين اللونين، ماذا لو قمنا بتقريب الصورة أكثر ؟
هذه هي الصورة بعد التقريب بنسبة 12800% تقريبا ( الخطان الأبيضان يمثلان الحد بين اللون القديم والجديد ):
تلاحظ أنه من غير الممكن أبدا التمييز بين اللونين بالعين المجردة ولا يمكن ملاحظة أي فرق، لكن كيف يفيدنا هذا في اخفاء البيانات؟
بما أن تغيير قيمة الـ Bit الأقل تأثيرا لا تُعد مشكلة بالنسبة للملف ( سواء كانت صورة أو مقطع صوت أو فيديو أو غيرها ) فإن بإمكاننا استخدام هذه الـ Bits في إخفاء بيانات أخرى، على سبيل المثال، هذا الـ Binary الخاص بهذا النص "code" :
01100011 01101111 01100100 01100101
لنفترض أن لدينا صورة نريد إخفاء هذا النص بداخلها، سنقوم بقراءة كل Pixel في الصورة، ونستخرج الـ Binary الخاص بالألوان فيه، ثم نُغير قيمة الـ Bit الأقل تأثيرا من كل لون إلى قيمة أحد الـ Bits الخاصة بالنص أعلاه، فالـ Pixel الأول من اليسار مثلا سيحتوي أول 3 Bits من النص السابق حيث يحتوي كل لون على Bit واحد من الـ Bits الخاصة بالنص، ستوضح لك هذه الصورة آلية عمل الخوارزمية نوعا ما، وستتضح أكثر عندما نكتب الكود الخاص بها:
المثال السابق يوضح الـ Binary الخاص بأول 7 بكسلات من صورة، وكما تلاحظ فإن كل لون يمثل ببايت واحد كما وضحنا مسبقا، في الأسفل ترى الـ Binary الخاص بكلمة "code" وقد قمت بتلوين أول 5 bits لإيضاح طريقة الإخفاء في الجدول على اليمين، بالطبع لن تكفي 7 بكسلات فقط لإخفاء هذه الكلمة، لكن المثال للتوضيح فقط.
مثال على استخدام خوارزمية LSB
سنكتب ونشرح الكود الخاص بالخوارزمية باستخدام لغة php، في هذا الشرح سنقوم باستخدام إضافة ImageMagick لـ PHP للتعامل مع الصور، قم بتنصيبها قبل بدء التطبيق على الدرس.
سنقوم بكتابة كلاس (Class) باسم StegHide، وسيحتوي على جميع الدوال التي ستلزمنا في عملية إظهار/إخفاء البيانات داخل الصورة:
class StegHide {
protected $image;
public function __construct(string $imagePath) {
$this->image = new Imagick($imagePath);
}
public function setImage(string $path) {
$this->image = new Imagick($path);
}
public function saveImage(string $name) {
$this->image->writeImage($name . '.png');
}
}
في الكلاس السابق لدينا متغير باسم image وسيحتوي على الصورة التي سنتعامل معها، عند انشاء Object من هذا الكلاس ستحتاج إلى تمرير مسار الصورة التي تريد إخفاء أو إظهار البيانات الخاصة بها، والدالة setImage ستستخدم لإعادة تعيين الصورة في حال اردنا استخدام نفس الـ Object مع صورة أخرى، وأخيرا الدالة saveImage ستقوم بتخزين الصورة كملف بصيغة png.
سنعمل أولا على آلية إخفاء البيانات، ثم نقوم بكتابة دالة إظهارها، لكن أولا يجب أن نعرف ما هي الخطوات التفصيلية لإخفاء البيانات، هذه صورة توضيحية ( قد تختلف في بعض تفاصيلها بحسب طريقة برمجتك للخاصية ):
كما ترى فإن هذه هي خطوات اخفاء الصورة، بعضها سيُكتب داخل دالة hideText مباشرة، والبعض الآخر سنضعه في دالة أخرى لتسهيل قراءة الكود وتنظيمه، وتسهيل اعادة استخدامه.
لاحظ الدالة ترجع قيمة عدد الـ Bits التي تم إخفاؤها، فالنص "abc" مثلا حجمه 3 Bytes أي ما يساوي 24 Bits ، وسنكون بحاجة لهذا الرقم لاستخدامه في عملية إظهار البيانات، فيجب على دالة اظهار البيانات أن تتوقف عن الدوران على البكسلات بعد قراءة كافة الـ Bits الخاصة بالنص، الأفضل طبعا إخفاء هذا الرقم داخل الصورة أيضا ضمن Byte محدد مثلا، حتى لا تضطر إلى تزويد الدالة بأي شيء عند الإظهار، لكن لتقليل الخطوات ضمن الشرح سنزود الدالة بعدد الـ Bits يدويا.
الخطوة الأولى هي تحويل النص إلى نظام العد الثنائي (Binary)، وأُفضل أن تكون هذه دالة مستقلة كالآتي:
protected function stringToBin(string $string): string {
$binary = '';
for ($i = 0; $i < strlen($string); $i++)
$binary .= sprintf('%08b', ord($string[$i]));
return $binary;
}
في البداية قمنا بتعريف متغير باسم binary، والذي سيحتوي على قيمة النص بعد التحويل، ثم قمنا بالدوران على جميع أحرف النص، وباستخدام الدالة ord يتم تحويل الحرف إلى رقم بنظام العد العشري Decimal، وهذا سيساعدنا في تحويله من نظام العد العشري إلى نظام العد الثنائي، فالدالة sprintf تقوم بإعادة ترتيب أو تنسيق النص الذي يُدخل إليها بحسب الصيغة التي تمررها لها وهي في هذه الحالة (08b%) وبهذا نكون قد طلبنا من الدالة باستخدام الحرف b أن تعامل المدخلات كرقم وتمثلها كـ Binary ( أي أنها تقوم بتحويل الـ Decimal إلى Binary ) أما (08) فوظيفتها إضافة 0 إلى يسار النص الناتج في حال كان طول النص أقل من 8، إلى أن يكتمل طول النص ويصبح 8، وفائدتها تحديد البيانات على أنها بحجم Byte، فمن دون هذه الإزاحة سيمثل الرقم (4) مثلا بهذه الطريقة ( 100 ) بينما نحن نريده هكذا ( 00000100 ).
وبعد تحويل جميع الأحرف إلى نظام العد Binary تقوم الدالة بارجاع المتغير binary.
الآن سنبدأ بالخطوة الثانية وهي قراءة بكسلات الصورة، كما في المثال:
public function hideText(string $text): int {
$binaryText = $this->stringToBin($text);
$iterator = $this->image->getPixelIterator();
foreach ($iterator as $row => $pixels) {
foreach ($pixels as $column => $pixel) {
# Pixel يجب أن نقوم بتحويل الألوان إلى النظام الثنائي هنا بعد قراءتها من المتغير
# الخاصة بالنص Bits الخاصة بالألوان وإدخال الـ Bits وهنا يجب أن نقوم بتعديل الـ
# كما يلزم نقوم بإعادة تحويل الألوان إلى النظام العشري لإعادة إدخالها إلى الصورة Bits بعد تعديل الـ
# فلا توجد حاجة لمتابعة الدوران Bits بعد الانتهاء من الخطوات السابقة يجب إيجاد آلية لإيقاف الدوران عند ادخال جميع الـ
}
$iterator->syncIterator();
}
return strlen($binaryText);
}
لاحظ التعليقات المكتوبة بداخل الدالة، وهي توضح الأجزاء الناقصة من هذه الدالة والتي سنكتبها واحدة واحدة، لكن قبل ذلك لنشرح ما كتبناه حتى الآن حتى يكون كل شيء واضحا قبل الانتقال للخطوة التالية.
في البداية قمنا باستدعاء الدالة التي كتبناها مسبقا لتحويل النص إلى Binary، وقمنا بتخزين ما ترجعه في المتغير binaryText، بعد ذلك قمنا بجلب الـ Iterator الذي يساعد بالدوران على بكسلات الصورة ( ميزة جاهزة في كلاس Imagick اضغط هنا لتفاصيل أكثر ) وقمنا بكتابة جمل الدوران، حيث أن كل صف من البكسلات يكون مخزنا في المتغير pixels، بينما الـ index الخاص بهذا الصف سيخزن في row، من ثم سييدور الدوران الثاني على كل بكسل في ذلك الصف، حيث يخزن الـ index الخاص بالعمود في column، بينما يخزن الـ Object الخاص بالتعامل مع البكسل في pixel، وباستخدام هذا الـ Object نستطيع القيام بالعديد من العمليات، وما يهمنا منها هنا هو جلب اللون أو تغييره.
بعد الانتهاء من الدوران على البكسلات داخل كل صف، يتم تنفيذ الدالة syncIterator وهي المسؤولة عن حفظ التعديلات التي نقوم بإجرائها على البكسلات.
الآن سنكتب دالة أخرى تستقبل Object من نوع ImagickPixel ( سنرسل لها المتغير pixel الموجود في الدالة السابقة )، ثم تقوم بإرجاع مصفوفة (Array) فيها نفس ألوان البكسل الذي قمنا بإرساله لكن بنظام Binary:
protected function colorToBin(ImagickPixel $pixel): array {
$colors = $pixel->getColor();
return [
sprintf('%08b', $colors['r']),
sprintf('%08b', $colors['g']),
sprintf('%08b', $colors['b'])
];
}
كما ترى فالدالة بسيطة جدا، نقوم بجلب الألوان من البكسل باستخدام getColor التي سترجع Associative Array تحتوي على الكثافة اللونية للألوان الثلاثة (RGB) والـ key الخاص بكل لون هو أول حرف من كل لون ( واضح بالمثال )، ثم نُرجع هذه القيمة على شكل array بعد تحويلها إلى binary باستخدام sprintf.
انظر الآن كيف أصبحت دالة الاخفاء بعد استدعاء الدالة السابقة والبدء بتعديل الـ Bits:
public function hideText(string $text): int {
$binaryText = $this->stringToBin($text);
$pointer = 0;
$shouldStop = false;
$iterator = $this->image->getPixelIterator();
foreach ($iterator as $row => $pixels) {
foreach ($pixels as $column => $pixel) {
#####################################################
$colors = $this->colorToBin($pixel); #
#
for ($i = 0; $i < 3; $i++) { #
$colors[$i][7] = $binaryText[$pointer]; #
#
$shouldStop = (++$pointer == strlen($binaryText)); #
if ($shouldStop) #
break; #
} #
#####################################################
# كما يلزم نقوم بإعادة تحويل الألوان إلى النظام العشري لإعادة إدخالها إلى الصورة Bits بعد تعديل الـ
####################
if ($shouldStop) #
break; #
####################
}
$iterator->syncIterator();
####################
if ($shouldStop) #
break; #
####################
}
return strlen($binaryText);
}
لاحظ الأجزاء الجديدة ( داخل المستطيلات )، في البداية قمنا باستدعاء الدالة التي كتبناها لتحويل الألوان من نظام العد العشري إلى نظام العد الثنائي، وقمنا بتخزينها في المتغير colors.
كذلك أضفنا for جديدة تقوم بالمرور على الألوان ( الأحمر والاخضر والازرق ) وتعدل الـ index السابع من كل Byte ( لأن السابع هو الأقل تأثيرا )، وبدلا من قيمته نضيف Bit واحد من الـ binary الخاص بالنص، ونقوم بتحديد المكان الذي وصلنا إليه باستخدام المتغير pointer، الذي تبدأ قيمته من صفر، وتزداد كلما اضفنا bit آخر.
وتلاحظ أننا أضفنا شروط داخل كل for، وهذه الشروط تتأكد من قيمة المتغير shoudStop، الذي يحتوي ناتج المقارنة بين القيمة التالية لـ pointer، وطول الـ Binary، ففي حال أصبح الـ pointer مساويا للطول، فهذا يعني أنه تم ادخال جميع الـ Bits إلى الصورة.
بقي الآن فقط أن نكتب الدالة التي تحول مصفوفة الألوان من Binary إلى Decimal واضافة الألوان إلى الصورة:
protected function binToColor(array $colors): string {
$r = bindec($colors[0]);
$g = bindec($colors[1]);
$b = bindec($colors[2]);
return "rgb($r, $g, $b)";
}
كما ترى، فالمصفوفة تستدعي فقط دالة bindec لتحويل كل لون، وتضع الألوان بداخل نص بصيغة مدعومة من كلاس ImagickPixel، الآن ننتقل إلى الاستدعاء وتكون دالة الإخفاء جاهزة:
public function hideText(string $text): int {
$binaryText = $this->stringToBin($text);
$pointer = 0;
$shouldStop = false;
$iterator = $this->image->getPixelIterator();
foreach ($iterator as $row => $pixels) {
foreach ($pixels as $column => $pixel) {
$colors = $this->colorToBin($pixel);
for ($i = 0; $i < 3; $i++) {
$colors[$i][7] = $binaryText[$pointer];
$shouldStop = (++$pointer == strlen($binaryText));
if ($shouldStop)
break;
}
##################################################
#
$pixel->setColor($this->binToColor($colors)); #
#
##################################################
if ($shouldStop)
break;
}
$iterator->syncIterator();
if ($shouldStop)
break;
}
return strlen($binaryText);
}
هكذا نكون قد انتهينا من كتابة دالة إخفاء النص بداخل الصورة. وإليك نبذة عن خطوات العمل لاستخراج النص:
أغلب الخطوات شرحناها مسبقا في شرحنا لإخفاء النص، لذلك سنكتب الدالة كاملة ونشرحها بشكل مختصر:
public function showText(int $length): string {
$iterator = $this->image->getPixelIterator();
$binaryText = '';
foreach ($iterator as $row => $pixels) {
foreach ($pixels as $column => $pixel) {
$colors = $this->colorToBin($pixel);
foreach ($colors as $color) {
$binaryText .= $color[7];
if (strlen($binaryText) == $length)
return $this->binToString($binaryText);
}
}
}
return false;
}
في البداية قمنا بتعريف الـ iterator ومتغير سيحتوي على الـ Binary التي سنحولها إلى نص. ثم قمنا بجلب لون البكسل داخل الدوران باستخدام دالة colorToBin التي عرفناها مسبقا.
ثم قمنا بالدوران على جميع الألوان وإضافة آخر Bit من كل لون إلى المتغير، ثم في حال تحقق الشرط بحيث أصبح طول الـ Bits المستخرج يساوي الطول الذي تم تزويد الدالة بها يتم إرجاع النص بعد تحويله باستخدام دالة binToString (لم نعرفها بعد) وهذه الدالة هي المسؤولة عن تحويل سلسلة الـ Binary التي حصلنا عليها إلى نص، وهو النص الذي تم إخفاؤه.
وهذا تعريف هذه الـ Method:
protected function binToString(string $binary): string {
$string = '';
$start = 0;
while ($start <= strlen($binary)) {
$string .= chr(bindec(substr($binary, $start, 8)));
$start += 8;
}
return $string;
}
ستقوم هذه الميثود بالدوران على كل Byte باستخدام substr، والمتغير start يزداد بمقدار 8 ( لكي يقرأ النص على شكل Bytes، وكل بايت يتم تحويله إلى رقم بنظام العد العشري باستخدام bindec، من ثم تحول هذا الرقم إلى حرف باستخدام chr، وتضيف كل حرف إلى المتغير string وتقوم بإرجاعه.
لنقم الآن بتجربة الكلاس، سنقوم بإخفاء عبارة "تجربة كتابة خوارزمية LSB على عالم البرمجة":
$stegObj = new StegHide('img.png');
# تعريف كائن جديد من الكلاس، وتحديد مسار الصورة
echo $stegObj->hideText('تجربة كتابة خوارزمية LSB على عالم البرمجة');
# استخدام دالة الإخفاء وطباعة القيمة التي سترجعها لاستخدامها لاظهار النص
$stegObj->saveImage('3alampro');
# حفظ الصورة الجديدة التي تحتوي على البيانات المخفية
والنتيجة:
إضافة إلى أنه قد تم إنشاء صورة جديدة باسم 3alampro.png، الآن لنجرب استرجاع البيانات المخفية:
$stegObj = new StegHide('3alampro.png');
echo $stegObj->showText(584);
والنتيجة:
الآن بامكانك ارسال الصورة الجديدة التي تحتوي على البيانات المخفية لأي شخص دون أن يلاحظ أحد أي تغيير على الصورة، هذه الصورة المستخدمة في المثال السابق مع الصورة التي تم إخفاء البيانات بداخلها:
يمكنك التجربة بنفسك وتحميل الصورة واظهار النص الموجود،
وهذا الكلاس كامل على Github:
https://github.com/3mmarg97/StegHide
ملاحظة: هذا الكلاس لا يُعد مشروعا كاملا، ولا يُنصح باستخدامه في بيئة إنتاجية أو في مشروع حقيقي، إنما هو كلاس بسيط كُتِب لغايات تعليمية فقط.
عرض المزيد.. جديد مقالاتي
عرض المزيد.. جديد دوراتي
لايوجد لديك حساب في عالم البرمجة؟
تحب تنضم لعالم البرمجة؟ وتنشئ عالمك الخاص، تنشر المقالات، الدورات، تشارك المبرمجين وتساعد الآخرين، اشترك الآن بخطوات يسيرة !