سؤال

ولست بحاجة لتقليد ما الخلية لا عند تشفير وفك تشفير سلاسل باستخدام المدمج في وظائف 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، ولكن هنا المقتطف المذكور:

http://pastie.org/425161

وخصيصا هذا الجزء:

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

وكنت المحددة! أيضا، يمكن العثور على رمز كاملة في هذا جست:

http://gist.github.com/84093

: -)

نصائح أخرى

وعموما كنت لا تريد لوحة المفتاح، كنت وسادة / unpad البيانات لتكون مشفرة / غير مشفرة. ويمكن أن يكون مصدر آخر من المشاكل. أنا أقترح استخدام بيانات الاختبار لعدد كامل من القطع للقضاء على هذا الاحتمال.

وأيضا، وأظن أن مفتاح لAPI بينسل يتطلب مفتاح "الحرفي"، وليس تمثيل ASCII من المفتاح لديك في التعليمات البرمجية.

ونظرا لندرة مستندات روبي بينسل وإذا كنت تتحدث قليلا جافا، قد ترغب في النموذج الأولي في JRuby مع مقدم BouncyCastle - وهذا هو الشيء الذي فعلته لتأثير جيد عند العمل مع TWOFISH (غير موجودة في بينسل API).

وتحرير: أنا أعيد قراءة تعليقك حول حشوة المفتاح. لديك بعض بت / بايت الارتباك في سؤالك، وأنا لست متأكدا كيف ينطبق هذا على أي حال منذ مفتاحك نشر و89 حرفا (712 بت) في الطول. ربما عليك أن تحاول مع 128 بت الرئيسية / كلمة المرور للقضاء على هذه الظاهرة الحشو؟

وبالمناسبة، يجب أن يضرب المشروعات الإنمائية الخلية لضعف التشفير، وهناك طرق أفضل لتمتد كلمات السر من ببساطة عن طريق الحشو مع بايت الصفر: (

إذا كنت لا تمانع في استخدام تنفيذ بينسل attr_encrypted هو جوهرة من شأنها أن تسمح في الانقطاع عن التشفير على معظم فئات، أكتيفيريكورد أم لا. أنه للأسف لن تكون متوافقة مع وظائف AES_EN / فك تشفير الخلية وبالرغم من ذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top