I've been using this open-source function to encrypt and decrypt strings via base64 methods, and I was wondering if there was a way to have a specific 'key' shared amongst me and some friends to make it work in a way where only the people who have this 'key' will properly encrypt or decrypt the messages.
-- Lua 5.1+ base64 v3.0 (c) 2009 by Alex Kloss <alexthkloss#web.de>
-- licensed under the terms of the LGPL2
-- character table string
local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
-- encoding
function enc(data)
return ((data:gsub('.', function(x)
local r,b='',x:byte()
for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
return r;
end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
if (#x < 6) then return '' end
local c=0
for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
return b:sub(c+1,c+1)
end)..({ '', '==', '=' })[#data%3+1])
end
-- decoding
function dec(data)
data = string.gsub(data, '[^'..b..'=]', '')
return (data:gsub('.', function(x)
if (x == '=') then return '' end
local r,f='',(b:find(x)-1)
for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end
return r;
end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
if (#x ~= 8) then return '' end
local c=0
for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
return string.char(c)
end))
end
So, say a similar function like this was given to me and three friends, and we all had a private string key called 'flibble'... How could we share messages undecipherable by others?
No, not with base 64. Base 64 is not encryption, it's encoding. Base 64 does not take a key as parameter, is just takes binary and converts it to printable ASCII.
There are of course tricks to make base 64 look a bit more like ciphertext: just put in a hustled alphabet (in your case in variable b). That's however common substitution; as such it should be considered obfuscation instead of encryption. I could explain to a random high-school student how to crack it.
Generally you need to first encrypt using a block cipher + mode of operation, and then perform the encoding. You'll need something like AES for the confidentiality and HMAC for the integrity and authenticity of messages.
I would recommend something like luacrypto. You really don't want to perform crypto using a high level language such as Lua for performance reasons alone. Many Lua libraries do offer just AES or HMAC but not both, and many seem one man projects instead of well supported/maintained libraries - so choose carefully.
Related
I want to sign a SHA-256 hash with DSA using PKCS#11 Java Wrapper for the PKCS#11 API of a hardware security module. For this purpose I selected the Mechanism CKM_DSA, load the corresponding DSA key from the token and have the data (read as byte-array) signed. The key I use for testing has 1024bit length.
Everything seems to work fine: The key is loaded, the Session.sign() yields a byte[] array of length 40. This corresponds to the PKCS#11 Spec, which says:
"For the purposes of this mechanism, a DSA signature is a 40-byte string,
corresponding to the concatenation of the DSA values r and s, each represented most significant byte first."
Now I want to verify this signature using openSSL, i.e., using
openssl dgst -d -sha256 -verify ${PUBLIC_KEY} -signature signature.der <raw input file>
This works if I
a) created the signature using OpenSSL
b) created the signature using bouncycastle and encoding the result as ASN1 encoded DER sequence.
Now I want to do the same with the PKCS#11 signature. My question is: how to format this 40 byte array? I tried the following:
//sign data
byte[] signedData = this.pkcs11Session.sign(dataToSign);
//convert result
byte[] r = new byte[20];
byte[] s = new byte[20];
System.arraycopy(signedData, 0, r, 0, 20);
System.arraycopy(signedData, 19, s, 0, 20);
//encode result
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(new ASN1Integer(r));
v.add(new ASN1Integer(s));
return new DERSequence(v).getEncoded(ASN1Encoding.DER);
The encoding part seems to be correct, because it works if I produce r and s directly with bouncycastle and another software key. Besides, openssl does accept the input format but the verification fails sometimes with an error, sometimes just with "Verification failure".
Thus, I assume the conversion of the PKCS#11 signature to r and s is wrong. Can someone help finding the mistake?
You probably have to convert the r and s values to a BigInteger class before you do. The reason for this is that ASN.1 uses signed value encoding and DH results in unsigned value encoding. So you've got a pretty high chance of getting a negative value in your ASN.1, which will result in an error.
To perform the conversion, use new BigInteger(1, r) and new BigInteger(1, s) and put the result into the ASN1Integer instances. Here 1 indicates that the value needs to be converted to a positive value (i.e. the input is unsigned positive).
I want to declare a constant as a 16 bit integer of type Word and assign a value to it. To support portability between Big and Little Endian platforms, I can't safely use an assignment like this one:
Special_Value : Constant Word := 16#1234#;
because the byte order might be misinterpreted.
So I use a record like this:
Type Double_Byte Is Record
Byte_1 : Byte; -- most significant byte
Byte_0 : Byte; -- least significant byte
End Record;
For Double_Byte Use Record
Byte_1 At 0 Range 0..7;
Byte_0 At 0 Range 8..15;
End Record;
However, in some cases, I have a large number of pre-configuration assignments that look like this:
Value_1 : Constant Word := 15#1234#;
This is very readable by a person, but endian issues cause it to be misunderstood a number of ways (including in the debugger, for example).
Because I have many lines where I do this, I tried the following because it is fairly compact as source code. It is working, but I'm not sure why, or what part of the Ada Reference Manual covers this concept:
Value_1 : Constant Word := DByte_To_Word((Byte_1 => 16#12#,
Byte_0 => 16#34#));
where DByte_To_Word is defined as
Function DByte_To_Word Is New Unchecked_Conversion(Double_Byte, Word);
I think I have seen something in the ARM that allows me to do this, but not the way I described above. I can't find it and I don't know what I would be searching for.
There’s nothing unusual about your call to DByte_To_Word; (Byte_1 => 16#12#, Byte_0 => 16#34#) is a perfectly legitimate record aggregate of type Double_Byte, see LRM83 4.3.1.
But! But! it’s true that, on a big-endian machine, the first (lowest-addressed) byte of your Word will contain 16#12#, whereas on a little-endian machine it will contain 16#34#. The CPU takes care of all of that; if you print the value of Special_Value you will get 16#1234# (or 0x1234) no matter which endianness the computer implements.
The only time you’ll encounter endianness issues is when you’re copying binary data from one endianness to another, via the network, or a file.
If your debugger gets confused about this, you need a better debugger!
I received the following data from a vendor so that we can decrypt data on our end.
Algorithm : AES 256bit
Key : test123xxxxxx
Key Length : 32
Initialize Vector: ei8B3hcD8VhnN_cK
Built in methods : YES (From inbuilt class CommonCryptor.h method with variable CCCryptorStatus).
Please note I have no idea if the last line has any relevance to our decryption.
I attempted the following on a sample string that we should be able to decode.
<cfset item = "eLgExhcox5Ro1kPB1OlJP1w6tEJ3x94gM/QJS5dCZkyjEVfNjIid3R7JP4l1WZD1" />
<cfoutput>#decrypt(#item#, #key#, 'AES', 'Base64', #iv# )#</cfoutput>
The error I receive is: The value of parameter 5, which is currently ei8B3hcD8VhnN_cK, must be a class [B value. of which I cannot find anything about.
I am also assuming the encoding is Base64 of which I am finding out from the vendor. Is there anything else I'm missing.
My guess would be it is complaining that the IV value is not binary. If your IV value is a base64 string, use binaryDecode(yourIVString, "base64") to get the binary value.
a class [B value
The [B refers to the expected object: an array of bytes. Apparently [B is the "binary name [...] as specified by the Java Language Specification (§13.1)". You will see the same thing if you create a byte[] array and dump the class name:
// show binary and canonical class names
arr = javacast("byte[]", [1]);
writeOutput("name="& arr.getClass().name);
writeOutput("<br>canonicalName="& arr.getClass().canonicalName);
Side note, if you are using a 256 bit key, be sure you have installed the (JCE) Unlimited Strength Jurisdiction Policy Files first. Otherwise, you are limited to 128 bit keys maximum.
I am trying to implement an AES-OFB wrapper around CNG's AES for symmetric encryption.
I have run into an issue that I cannot understand... I have created an AES algorithm handle (BCRYPT_AES_ALGORITHM) and imported an AES key. I then attempt to generate a 16 byte keystream for use with XORing my plaintext/ciphertext. The first time I run through this mechanism, the keyStreamPtr changes from some random byte stream to another, however, the 3rd time I do this (the 3rd set of 16 bytes of keystream), I start getting the same output and it happens forever.
status = BCryptEncrypt((BCRYPT_KEY_HANDLE)keyHandle,
keyStreamPtr,
keyStreamLength,
NULL, //no padding
NULL, // no IV
0, // no IV
keyStreamPtr,
keyStreamLength,
&Length,
0); // no option flags
Has anybody ever seen anything like this? why would AES ever return ciphertext totally identical to the plaintext that was the input? Again this is for an AES-OFB implementation... Perhaps I am doing something wrong?
The only thing I can think of is that you encrypt the key stream again. If you do this you effectively perform encrypt/decrypt: P XOR C XOR C = P where C is the key stream and P is the plain text. You might want to look at the buffer/stream handling within your code.
I have pasted a code below which is in Ada language.I need some clarification on some implementations.
C : character;
Char : character;
type Myarr_Type is array (character range 'A'..'K') of character;
Myarr : Myarr_Type := ('A','B','C','D','E','F','G','H','I','J','K');
Next_Address := Myarr'address --'
Last_Address := Next_Address + Storage_Offset'(40); --'
return P2 + Storage_Offset'(4); --'
Last_Address := Next_Address + Storage_Offset'(4); --'
Now my doubt is 1) what does P2 + Storage_Offset'(4) actually mean.Does that mean that its returning the address of the next element in the array which is 'B'.Storage_Offset'(4) in Ada --does this mean 4 bits or 4 bytes of memory. 2) If i assume that Last_Address points to last element of the array which is 'K', how does the arithmentic Storage_Offset'(40) satisfies the actual implementation?
Please get back to me if u need any more clarifications.
Please assume that the function does not exist.
As a matter of fact,i have some ada file and my job is to convert them to C files.Since i am a beginner in ada,i faced a lot of issues with that.Please pardon in case of any confusion
Thanks
Maddy
Storage_Offset is a special integeral type in package System.Storage_Elements that can be added to objects of type System.Address. What exactly the units of Address and Storage_Offset are is implementation defined, but probably just about every implementation in existence uses bytes. So Next_Address + Storage_Offset'(4) means "the address four bytes past whatever Next_Address refers to."
You talked a bit about Ada porting. In 99% of cases, that is a very stupid idea (the %1 being when you need to port to a platform that has no Ada compiler). I'd say the same thing no matter what language you are porting. It's a fool's game. The best outcome you can hope for when porting code is that after a ton of effort it works as well as it did before. With coding the best case never happens.
Ada can interface to C just fine, so it would be far smarter to keep unchanged code in Ada and only "port" stuff you need to change.
If you come across any tasking code, protected types, or custom streams you will be in a world of hurt. Those things don't really have easy C analogs.
If your bosses really have a boner for C or something, I'd suggest looking into Sofcheck's AdaMagic, which provides a service to transform Ada code to ANSI C. Back in the day (two owners prior) they used to claim that it produced maintainable C code. Either way, it will probably be far cheaper than having an inexperienced (in Ada) developer try to do it all by hand.
my_func(int P1,int P2)
{
return P2 + Storage_Offset'(4);
}
Well, this is a C function whose body is written in Ada. There is no "+" operator taking an Integer and a Storage_Offset; perhaps you're looking for
function "+"(Left : Address; Right : Storage_Offset)
return Address;
and perhaps you meant to call my_func(something, Next_Address)?
In that case, the expression will return the address of whatever is 4 Storage_Elements, ie bytes, after Myarr('A').
Myarr_Type is an array of Character, which with any normal compiler on any common architecture is going to be a standard 8-bit byte. So Myarr_Type objects will be 11 bytes long, not 44, and Myarr('A')'Address + 4 will be the address of Myarr('E').
If you want the address of the last element of Myarr, try
Myarr (Myarr'Last)'Address