If you are storing it "just in case" but don't expect to use it, I
would use a public key system, such as RSA. In RSA, you keep one of
the keys (the public one) on the server, and it encrypts data. To get
it out, you need the private key. People can hack away but so long as
they don't have the private key, they cannot read your data. (more
hand waving here, it IS possible, but we're entering into the world of
theoretical quantum computing here.)
The numerous times I've had to handle CC data I was explicitly
forbidden to store the numbers (card, expiry date, or CCV) other than
the last 6 digits of the card. I could store anything returned from
the processor though, like auth numbers, status codes, etc. This was
in all our cases sufficient to reverse charges (if needed) or to bill
in a recurring manner.
As for the examples, I think your "irb" is hiding data from you. Try
something like:
x = AESCrypt.encrypt(...)
AESCrypt.decrypt(x, ...)
I think your output is the same as mine, you just have ? marks where I
have some \301 escaped characters.
--Michael
Hi,
I wonder whether this was resolved.
I'm having a similar issue.
I encrypt using a Flash AES CTS cipher from the library (hurlant). I'm
decrypting in Ruby. When used in Flash for both encrypt and decrypt,
all is joyous. However, when I try to use the openSSL package within
Ruby - the one mentioned above, I am able to decrypt most of the cipher
text. However, the last 17 bytes are garbled.
Lots of Google searching...
This is a test system, and in it, I set the IV to 16 bytes of 0. (I
really don't want to be yelled at here about the lack of security in
such a scheme)...
I get the same 'OpenSSL::CipherError: wrong final block length' error
when calling the 'final' method. 'update' works like a charm. I see
all of the clear test, in 32 byte chunks, up to the last partial block.
Then, I see garbled data in the last partial.
So, I'm guessing either the hurlant package handles the last partial
differently than Ruby's openSSL, or (much much much more likely), I am
doing something obviously wrong.
Could a kind soul please let me know if they have experience and
overcome such a problem?
Thanks,
Mike
--
Posted via http://www.ruby-forum.com/.
You are probably running into padding issues. Since AES is a block
cypher, each block must be exactly the correct length I suspect.
How are you calling the decrypt code? You're just feeding data into
the encryption system and after you are all done with the data,
calling final? That should work, but I do not have any way to write
code in Flash to test this. If you could have Flash encrypt
something, perhaps 101 bytes or so long (odd to ensure padding
occurs), and send the plaintext, the key, and the encrypted string
(uuencode, hex dump, whatever) I can experiment.
--Michael
Hi,
Thanks... Definitely appears to be padding issues. We are using Bouncy
Castle CTS AES encrypt. The openSSL appears to be using CBC. I'm no
expert... In looking at the RFC, it appears there is a difference
between how CBC and CBC/CTS handles padding. There is a reference in
the rfc to swapping within the last partial block as part of the
process... not sure how/whether this is implemented.
Below is the output from my irb session. The clear text is supposed to
be:
AAAAAAAABBBBBBBBAAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDCCCCCCCCDDDDDDDDAAAAAAAABBBBBBBBAAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDCCCCCCCCDDDDDDDDXXXYYY
key: 4b1114cc73fed8b5428c3dee60d7773a
Please notice that the first part of the message is decrypted
correctly.... the partial at the end is not.
irb(main):821:0> a= OpenSSL::Cipher::Cipher.new('aes-256-cbc')
=> #<OpenSSL::Cipher::Cipher:0xb79b9378>
irb(main):822:0> a.key=d
=> "4b1114cc73fed8b5428c3dee60d7773a"
irb(main):823:0>
a.iv='00000000000000000000000000000000'.unpack('a2'*32).map{|x|
x.hex}.pack('c'*32)=>
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
irb(main):824:0>
data='TmI9HrNrsMBxSfwApvSaQrLIDsLboNhIW/FawPjNUB0x/G0ZDf+gfk4JaTc/tGxDg1s4mrIRFOoBJemK+txUF0+aPw8bxIgzxmB3gq18aJRoSo5PWqbzS8FCCHrb3leKf4UUNFaIAaVVY1a5ymZ/HMPhwAKbii8x9Uk/S0MxaDofHTluc1E='.unpack('m')[0]
=>
"Nb=\036\263k\260\300qI\374\000\246\364\232B\262\310\016\302\333\240\330H[\361Z\300\370\315P\0351\374m\031\r\377\240~N\ti7?\264lC\203[8\232\262\021\024\352\001%\351\212\372\334T\027O\232?\017\e\304\2103\306`w\202\255|h\224hJ\216OZ\246\363K\301B\bz\333\336W\212\177\205\0244V\210\001\245UcV\271\312f\177\034\303\341\300\002\233\212/1\365I?KC1h:\037\0359nsQ"
irb(main):825:0> s=a.update(data)
=>
"AAAAAAAABBBBBBBBAAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDCCCCCCCCDDDDDDDDAAAAAAAABBBBBBBBAAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD8\300u\003|\200\243jf\bkf\005\251\327\242"
irb(main):826:0> s<<a.final
OpenSSL::Cipher::CipherError: wrong final block length
from (irb):826:in `final'
from (irb):826
from :0
irb(main):827:0>
As a follow on, I was just reading an interesting article on Wikipedia.
Here's a snippet from it:
CBC ciphertext stealing decryption using a standard CBC interface
1. Dn = Decrypt (K, Cn−1). Decrypt the second to the last ciphertext
block.
2. Cn = Cn || Tail (Dn, B−M). Pad the ciphertext to the nearest
multiple of the block size using the last B−M bits of block cipher
decryption of the second-to-last ciphertext block.
3. Swap the last two ciphertext blocks.
4. Decrypt the ciphertext using the standard CBC mode.
5. Truncate the plaintext to the length of the original ciphertext.
Looks like the above is the mechanism to translate the last couple of
blocks of ciphertext to a form understandable by the CBC interface.
I think I understand points 1, 3, 4, and 5. I'm having a tougher time
with number 2, but I get the basic idea.
Let's say the the message is 134 bytes long. Then, I'd do 134 % 16 and
I get 6. If my block size is 128 bits (16 bytes*8 bits), then I'd
subtract 48 bits (6 bytes * 8 bits). That means 80 bits would be used
as a repeated pattern to pad the end of the message to make it evenly
divisible by 16. So, I'd add in one iteration (10 bytes) in this case,
to bring the message to 144 bytes (evenly divisible by the block size -
16).
Anyway, that's what I'm going to try. Please wish me luck ;-)
Mike
Well... not what I was hoping for... Below is the Ruby code I wrote to
try to implement what I thought Wikipedia was getting at...
When I try to decipher the next to last block, the result comes back
nil. Therefore, there is nothing to pad to the end of the cipher
string.
The good news is, a colleague of mine pointed me to some c code. I was
experimenting with it last night and I was able to decipher characters
at the end of the string. That implementation called for the Xor of the
final blocks. It's not in a script yet... was working in IRB. Will
post that solution once I've completed it today.
But would really appreciate any comments on whether the Wikipedia
reference is correct, and if so, what the heck is wrong with the way I
tried to implement it.
Thanks!
Mike
require 'openssl'
require 'digest'
#set the cipher text and unpack
ct='TmI9HrNrsMBxSfwApvSaQrLIDsLboNhIW/FawPjNUB0x/G0ZDf+gfk4JaTc/tGxDg1s4mrIRFOoBJemK+txUF0+aPw8bxIgzxmB3gq18aJRoSo5PWqbzS8FCCHrb3leKf4UUNFaIAaVVY1a5ymZ/HMPhwAKbii8x9Uk/S0MxaDofHTluc1E='.unpack('m')[0]
aes=nil
#set the cipher
aes = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
#set it to decrypt mode
aes.decrypt
#set the decryption key
aes.key='4b1114cc73fed8b5428c3dee60d7773a'
#set up the IV
aes.iv='00000000000000000000000000000000'.unpack('a2'*32).map{|x|
x.hex}.pack('c'*32)
#mod the string to find the partial block length
partialBlockLength = ct.length % 16
#this is the index of the cbc decrypted output:
endOfOutput = ct.slice(0..ct.length-16-partialBlockLength).length
#grab the next to last block
section = ct.slice(ct.length-partialBlockLength-16..ct.length -
partialBlockLength-1)
#decipher the next to last block
decihperedLastCompleteBlock = aes.update(section)
#pad the end of the cipher with the last blockSize-partialBlockLength
ct<<decihperedLastCompleteBlock.slice(decihperedLastCompleteBlock.length-(16-partialBlockLength)..decihperedLastCompleteBlock.length-1)
#swap the last two blocks
src=ct.slice(0..endOfOutput) + ct.slice(ct.length-16..ct.length-1) +
ct.slice(ct.length-32..ct.length-17)
aes=nil
#set the cipher
aes = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
#set it to decrypt mode
aes.decrypt
#create the digest
d=Digest::MD5.hexdigest('7R]c\'1z<q\\O%eybO:michael_cook_611')
#set the decryption key
aes.key=d
#set up the IV
aes.iv='00000000000000000000000000000000'.unpack('a2'*32).map{|x|
x.hex}.pack('c'*32)
output = aes.update src
I hope this helps some other folks in Ruby land. Please suggest some
ways to better document the steps.
Take care,
Mike
#key
d='4b1114cc73fed8b5428c3dee60d7773a'
tmpArray=nil
aes=nil
alpha=nil
omega=nil
#cipher text, unpacked from Base64
a='TmI9HrNrsMBxSfwApvSaQrLIDsLboNhIW/FawPjNUB0x/G0ZDf+gfk4JaTc/tGxDg1s4mrIRFOoBJemK+txUF0+aPw8bxIgzxmB3gq18aJRoSo5PWqbzS8FCCHrb3leKf4UUNFaIAaVVY1a5ymZ/HMPhwAKbii8x9Uk/S0MxaDofHTluc1E='.unpack('m')[0]
#compute the extra cipher beyond a 16 byte boundary
partial = a.length % 16
#set up the beginning and end of the CTS blocks we need to work on
alpha = a.length-16-partial
omega = a.length-1
#grab the end of the cipher
c=a.slice(alpha..omega)
#start + partial..end-partial
c<<a.slice(alpha+partial..omega-partial)
#first decrypt the beginning
aes = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
aes.decrypt
aes.key=d
aes.iv='00000000000000000000000000000000'.unpack('a2'*16).map{|x|
x.hex}.pack('c'*16)
firstBlock=aes.update a.slice(0..((a.length/32)*32)-1)
#next decrypt the end
aes = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
aes.decrypt
aes.key=d
aes.iv='00000000000000000000000000000000'.unpack('a2'*16).map{|x|
x.hex}.pack('c'*16)
decrypted3=aes.update c
lastBlock=""
#here we need to Xor the result against the contents of end of the
undecrypted cipher text
(0..partial-1).each {|index| tmpA='';tmpA=
(decrypted3[index]^c[16+index]).chr; lastBlock<<tmpA}
#put a number of bytes of undecrypted c then followed with the last
number of the decrypted c... the number of bytes sliced depends upon the
number of bytes in the partial block at the end of the cipher...
tmpArray =
c.slice(16..16+partial-1)<<decrypted3.slice(partial..decrypted3.length-1)
#now handle the middle
aes = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
aes.decrypt
aes.key= d
aes.iv='00000000000000000000000000000000'.unpack('a2'*16).map{|x|
x.hex}.pack('c'*16)
tmpArray=tmpArray<<tmpArray
middle=aes.update tmpArray
#now take the last block of the decipherable original block
last = a.slice(alpha-16..alpha-1)
midBlock=""
#and ^or it against the middle component
(0..middle.length-1).each {|index|
tmpB='';tmpB<<(middle[index]^last[index]).chr;midBlock<<tmpB}
finalBlock = firstBlock+midBlock+lastBlock