تقليد وظائف AES_ENCRYPT وAES_DECRYPT في روبي
-
21-08-2019 - |
سؤال
ولست بحاجة لتقليد ما الخلية لا عند تشفير وفك تشفير سلاسل باستخدام المدمج في وظائف AES_ENCRYPT () وAES_DECRYPT ().
ولقد قرأت بضعة بلوق وظائف ويستخدم على ما يبدو الخلية AES تشفير 128 بت لتلك الوظائف. وعلاوة على ذلك، لأن هذا التشفير يتطلب مفتاح 16 بت، الخلية منصات السلسلة مع حرف X0 (\ 0S) حتى انها 16 بت في الحجم.
ورصدت الخوارزمية في C من شفرة المصدر الخلية هنا .
والآن أنا بحاجة لتكرار ما تقوم الخلية في تطبيق القضبان، ولكن كل شيء واحد حاولت، لا يعمل.
وهنا طريقة لتكرار السلوك أنا على الحصول على:
1) إنشاء التطبيق القضبان جديد
rails encryption-test
cd encryption-test
2) إنشاء السقالات جديدة
script/generate scaffold user name:string password:binary
و3) عدل التكوين / database.yml وإضافة قاعدة بيانات MySQL اختبار
development:
adapter: mysql
host: localhost
database: test
user: <<user>>
password: <<password>>
و4) تشغيل الهجرة
rake db:migrate
و5) أدخل وحدة التحكم، إنشاء المستخدم وكلمة المرور الخاصة به تحديث من الخلية الاستعلام
script/console
Loading development environment (Rails 2.2.2)
>> User.create(:name => "John Doe")
>> key = "82pjd12398JKBSDIGUSisahdoahOUASDHsdapdjqwjeASIduAsdh078asdASD087asdADSsdjhA7809asdajhADSs"
>> ActiveRecord::Base.connection.execute("UPDATE users SET password = AES_ENCRYPT('password', '#{key}') WHERE name='John Doe'")
وهذا هو حيث حصلت على تمسك. إذا كنت تحاول فك تشفيرها باستخدام الخلية يعمل:
>> loaded_user = User.find_by_sql("SELECT AES_DECRYPT(password, '#{key}') AS password FROM users WHERE id=1").first
>> loaded_user['password']
=> "password"
ولكن إذا كنت تحاول استخدام مكتبة بينسل، وليس هناك طريقة يمكنني جعله العمل:
cipher = OpenSSL::Cipher::Cipher.new("AES-128-ECB")
cipher.padding = 0
cipher.key = key
cipher.decrypt
user = User.find(1)
cipher.update(user.password) << cipher.final #=> "########gf####\027\227"
ولقد حاولت حشوة مفتاح:
desired_length = 16 * ((key.length / 16) + 1)
padded_key = key + "\0" * (desired_length - key.length)
cipher = OpenSSL::Cipher::Cipher.new("AES-128-ECB")
cipher.key = key
cipher.decrypt
user = User.find(1)
cipher.update(user.password) << cipher.final #=> ""|\e\261\205:\032s\273\242\030\261\272P##"
ولكن هل حقا لا يعمل.
لا أحد لديه أدنى فكرة عن كيف يمكنني تقليد الخلية AES_ENCRYPT () وAES_DECRYPT () السلوك وظائف في روبي؟
وشكرا!
المحلول
لتكون مرجعا في المستقبل:
ووفقا لآخر بلوق وجهت من قبل، وهنا كيف تعمل الخلية مع المفتاح الذي تقدم AES_ENCRYPT / فك تشفير:
<اقتباس فقرة>و"الخوارزمية فقط يخلق 16 بايت المخزن المؤقت المقرر أن جميع صفر، ثم حلقات من خلال جميع الشخصيات من سلسلة التي تقدمها ولا أحد احالة مع أحادي المعامل OR بين قيمتين. إذا كنا تكرار حتى نحن ضرب نهاية المخزن المؤقت 16 بايت، ونحن مجرد البدء من جديد من البداية القيام ^ =. سلاسل أقصر من 16 الشخصيات، نتوقف عند نهاية السلسلة ".
اقتباس فقرة>وأنا لا أعرف إذا كنت تستطيع قراءة C، ولكن هنا المقتطف المذكور:
وخصيصا هذا الجزء:
bzero((char*) rkey,AES_KEY_LENGTH/8); /* Set initial key */
for (ptr= rkey, sptr= key; sptr < key_end; ptr++,sptr++)
{
if (ptr == rkey_end)
ptr= rkey; /* Just loop over tmp_key until we used all key */
*ptr^= (uint8) *sptr;
}
وهكذا خطرت لي هذه الطريقة (مع مساعدة من روب Biedenharn، من منتدى روبي):
def mysql_key(key)
final_key = "\0" * 16
key.length.times do |i|
final_key[i%16] ^= key[i]
end
final_key
end
وهذا، نظرا لسلسلة إرجاع الخلية الأساسية يستخدم عند تشفير وفك تشفير. ذلك كل ما عليك الآن هو:
def aes(m,k,t)
(aes = OpenSSL::Cipher::AES128.new("ECB").send(m)).key = k
aes.update(t) << aes.final
end
def encrypt(key, text)
aes(:encrypt, key, text)
end
def decrypt(key, text)
aes(:decrypt, key, text)
end
لاستخدام ليب بينسل، الذي بني في روبي، وبعد ذلك يمكنك جعل طريقتين "النهائية":
def mysql_encrypt(s, key)
encrypt(mysql_key(key), s)
end
def mysql_decrypt(s, key)
decrypt(mysql_key(key), s)
end
وكنت المحددة! أيضا، يمكن العثور على رمز كاملة في هذا جست:
: -)
نصائح أخرى
وعموما كنت لا تريد لوحة المفتاح، كنت وسادة / unpad البيانات لتكون مشفرة / غير مشفرة. ويمكن أن يكون مصدر آخر من المشاكل. أنا أقترح استخدام بيانات الاختبار لعدد كامل من القطع للقضاء على هذا الاحتمال.
وأيضا، وأظن أن مفتاح لAPI بينسل يتطلب مفتاح "الحرفي"، وليس تمثيل ASCII من المفتاح لديك في التعليمات البرمجية.
ونظرا لندرة مستندات روبي بينسل وإذا كنت تتحدث قليلا جافا، قد ترغب في النموذج الأولي في JRuby مع مقدم BouncyCastle - وهذا هو الشيء الذي فعلته لتأثير جيد عند العمل مع TWOFISH (غير موجودة في بينسل API).
وتحرير: أنا أعيد قراءة تعليقك حول حشوة المفتاح. لديك بعض بت / بايت الارتباك في سؤالك، وأنا لست متأكدا كيف ينطبق هذا على أي حال منذ مفتاحك نشر و89 حرفا (712 بت) في الطول. ربما عليك أن تحاول مع 128 بت الرئيسية / كلمة المرور للقضاء على هذه الظاهرة الحشو؟
وبالمناسبة، يجب أن يضرب المشروعات الإنمائية الخلية لضعف التشفير، وهناك طرق أفضل لتمتد كلمات السر من ببساطة عن طريق الحشو مع بايت الصفر: (
إذا كنت لا تمانع في استخدام تنفيذ بينسل attr_encrypted هو جوهرة من شأنها أن تسمح في الانقطاع عن التشفير على معظم فئات، أكتيفيريكورد أم لا. أنه للأسف لن تكون متوافقة مع وظائف AES_EN / فك تشفير الخلية وبالرغم من ذلك.