Is Sha256Hash from Apache Shiro based upon a common specification like PBKDF2WithHmacSHA256?
The following example proves, Shiros Sha256Hash doesn't create a valid PBKDF2WithHmacSHA256 hashes.
public static byte[] getEncryptedPassword(
String password,
byte[] salt,
int iterations,
int derivedKeyLength
) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeySpec keySpec = new PBEKeySpec(
password.toCharArray(),
salt,
iterations,
derivedKeyLength * 8
);
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
return f.generateSecret(keySpec).getEncoded();
}
#Test
public void testHashing(){
byte[] salt = new SecureRandomNumberGenerator().nextBytes().getBytes();
byte[] hash1 = new Sha256Hash("1234", salt, 1024).getBytes();
byte[] hash2 = getEncryptedPassword("1234", salt, 1024, 32);
assertTrue(hash1.equals(hash2));
}
Is there a common way to use PBKDF2WithHmacSHA256 with shiro, or do I have to implement my own CredentialMatcher?
Per the Shiro user list on nabble no, Shiro does not provide PBKDF2 (or BCrypt or SCrypt).
Note that Java 8 does have PBKDF2-HMAC-SHA-512 available now as PBKDF2WithHmacSHA512 - use that instead. SHA-512 in particular has 64-bit operations that reduce the advantage GPU based attackers have. Use more iterations than just 1024, as well - see what your system can handle comfortably under load!
Related
I am studying at night graduate school.
While studying the cryptographic hash function, I found information that the speed of the SHA3 hash function is faster than the speed of the SHA2 hash function.
So, using JMH benchmarking in actual JAVA, I tried to compare the performance of SHA512/256 of SHA2 and SHAKE256 of SHA3 series, but there doesn't seem to be much difference than I thought.
The library I used and the source code I wrote are as follows.
SHA512-256
import java.security.MessageDigest;
public static byte[] digest(byte[] data) throws NoSuchAlgorithmException
{
CryptoProvider.setupIfNeeded();
java.security.MessageDigest digest = java.security.MessageDigest.getInstance("SHA512/256");
digest.update(Arrays.copyOf(data, data.length));
return digest.digest();
}
SHAKE256 (use 2 methods)
import org.bouncycastle.crypto.digests.SHAKEDigest;
public static byte[] shakeDigest(byte[] data, int returnLength) throws NoSuchAlgorithmException
{
CryptoProvider.setupIfNeeded();
SHAKEDigest digest = new SHAKEDigest(256);
byte[] hashBytes = new byte[returnLength];
digest.update(data, 0, data.length);
digest.doFinal(hashBytes, 0);
digest.reset();
return Arrays.copyOf(hashBytes, returnLength);
}
import com.github.aelstad.keccakj.fips202.Shake256;
public static byte[] shakeDigest2(byte[] data, int returnLength) throws Exception
{
CryptoProvider.setupIfNeeded();
Shake256 digest = new Shake256();
digest.getAbsorbStream().write(data);
byte[] hashBytes = new byte[returnLength];
digest.getSqueezeStream().read(hashBytes);
digest.reset();
return Arrays.copyOf(hashBytes, returnLength);
}
I'm wondering if I'm missing something, or if there exists a SHAKE256 library that's closer to perfection than the one I used.
Please help.
Thank you.
I generate a 128-bit AES object using "C_CreateObject".
I then do the following to encrypt a piece of data and get a "Bad Argumnents" error on the call to "C_Encrypt" to get the encrypted data length.
char clear[] = "My name is Eric!";
buf_len = sizeof(clear) -1;
rv = pfunc11->C_EncryptInit(session, pMechanism, hObject);
if (rv != CKR_OK)
{
printf("ERROR: rv=0x%08X: initializing encryption:\n", (unsigned int)rv);
return false;
}
rv = pfunc11->C_Encrypt(session, (CK_BYTE_PTR)clear, (CK_ULONG)buf_len, NULL, pulEncryptedDataLen);
if (rv != CKR_OK)
{
printf("ERROR: rv=0x%08X: derror getting encryption data buffer length:\n", (unsigned int)rv);
return false;
}
What am I doing wrong here ?
Here is my mechanism definition -
CK_MECHANISM myMechanism = {CKM_AES_CBC_PAD, (CK_VOID_PTR)"01020304050607081122334455667788", (CK_ULONG)16};
CK_MECHANISM_PTR pMechanism = &myMechanism;
Your pulEncryptedDataLen is probably NULL which causes CKR_ARGUMENTS_BAD.
It is better to use e.g.:
CK_ULONG ulEncryptedDataLen;
...
rv = pfunc11->C_Encrypt(session, (CK_BYTE_PTR)clear, (CK_ULONG)buf_len, NULL, &ulEncryptedDataLen);
The number of bytes sufficient to store encryption result of a single-part encryption gets stored into ulEncryptedDataLen.
Also please note that your way of passing IV value is not correct as "01020304050607081122334455667788" results in an ASCII string (giving IV as 30313032303330343035303630373038 -- which is probably not what you want).
To get correct IV use "\x01\x02\x03\x04\x05\x06\x07\x08\x11\x22\x33\x44\x55\x66\x77\x88" instead.
Good luck!
I have implemented Digital Signature using iTextSharp Dll to sign PDF files with a single signature creating empty signature fields and update the signature field with signed hash working fine. Now, I want to place the same digital signature in every page of pdf. It's my client requirement.
I’m using the following code:
public class MyExternalSignatureContainer : IExternalSignatureContainer
{
private readonly byte[] signedBytes;
public MyExternalSignatureContainer(byte[] signedBytes)
{
this.signedBytes = signedBytes;
}
public byte[] Sign(Stream data)
{
return signedBytes;
}
public void ModifySigningDictionary(PdfDictionary signDic)
{
}
}
Below code used in program
PdfReader reader = new PdfReader(unsignedPdf);
FileStream os = File.OpenWrite(tempPdf);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = "Reason1";
appearance.Contact = "";
appearance.Location = "Location1";
appearance.Acro6Layers = false;
appearance.Image = null;
appearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.DESCRIPTION;
appearance.SetVisibleSignature(new iTextSharp.text.Rectangle(36, 748, 144, 780), 1, null);
for (int i = 1; i < 8; i++)
{
var signatureField = PdfFormField.CreateSignature(stamper.Writer);
var signatureRect = new Rectangle(200, 200, 100, 100);
signatureField.Put(PdfName.T, new PdfString("ClientSignature_"+i.ToString()));
PdfIndirectReference PRef = stamper.Writer.PdfIndirectReference;
signatureField.Put(PdfName.V, PRef);
signatureField.Put(PdfName.F, new PdfNumber("132"));
signatureField.SetWidget(signatureRect, null);
signatureField.Put(PdfName.SUBTYPE, PdfName.WIDGET);
PdfDictionary xobject1 = new PdfDictionary();
PdfDictionary xobject2 = new PdfDictionary();
xobject1.Put(PdfName.N, appearance.GetAppearance().IndirectReference);
xobject2.Put(PdfName.AP, xobject1);
signatureField.Put(PdfName.AP, xobject1);
signatureField.SetPage();
PdfDictionary xobject3 = new PdfDictionary();
PdfDictionary xobject4 = new PdfDictionary();
xobject4.Put(PdfName.FRM, appearance.GetAppearance().IndirectReference);
xobject3.Put(PdfName.XOBJECT, xobject4);
signatureField.Put(PdfName.DR, xobject3);
stamper.AddAnnotation(signatureField, i);
}
IExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKMS, PdfName.ADBE_PKCS7_DETACHED);
MakeSignature.SignExternalContainer(appearance, external, 8192);
stamper.Close();
byte[] SignedHash = DoEsign(SHA256Managed.Create().ComputeHash(appearance.GetRangeStream());
os.close();
reader.close();
reader = new PdfReader(tempPdf))
os = File.OpenWrite(signedPdf)
IExternalSignatureContainer external1 = new MyExternalSignatureContainer(SignedHash);
MakeSignature.SignDeferred(reader, signatureFieldName, os, external1);
os.close();
reader.close();
Please suggest me to complete the task
To give all signature fields the same single value wrapping the newly created signature container, they must all reference the same indirect object as value. Unfortunately iText creates the indirect object for the signature value only after the application code had the chance to add its additional fields which in turn require a reference to that signature value object. Thus, the application code has to anticipate the object number that indirect object will have.
This anticipation or prediction of the object number is very delicate, it depends on the exact same use case and can also become incorrect as the result of minor changes in the iTextSharp library
To make this easier, the application code should add those signature fields with their signature value references as late as possible, so there are as few other new indirect objects created as possible until iText creates the value indirect object.
As it turns out, the ModifySigningDictionary method of an IExternalSignatureContainer is a good position for that.
As soon as one adds one's code there, another issue pops up: There is no means to set the anticipated object number in a PdfIndirectReference instance externally. One way to get around this is to mimic such a reference using a PdfLiteral. (Well, probably one could also use reflection for this.)
Furthermore it turns out that one best creates the appearance streams to use by all one's additional signature fields before building that PdfLiteral mimicking a PdfIndirectReference as this simplifies the calculation of the object number iText will use for the actual value object.
With this in mind, here a proof-of concept. This proof of concept makes use of an IExternalSignature instance for actually signing. This is not a necessary precondition, one can also use an IExternalSignatureContainer instead with only a few changes, even an ExternalBlankSignatureContainer as in the question to later finalize the signature using MakeSignature.SignDeferred.
So given cipher parameters cp (private key material, e.g. pk.Key for an Org.BouncyCastle.Pkcs.AsymmetricKeyEntry pk) and a certificate chain chain, one would use
PdfReader reader = new PdfReader(SRC);
FileStream os = new FileStream(DEST, FileMode.Create, FileAccess.Write);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = "Reason1";
appearance.Contact = "";
appearance.Location = "Location1";
appearance.Acro6Layers = false;
appearance.Image = null;
appearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.DESCRIPTION;
appearance.SetVisibleSignature(new iTextSharp.text.Rectangle(10, 10, 100, 100), reader.NumberOfPages, null);
IExternalSignature externalSignature = new PrivateKeySignature(cp, "SHA-256");
AllPagesSignatureContainer allPagesContainer = new AllPagesSignatureContainer(appearance, externalSignature, chain);
MakeSignature.SignExternalContainer(appearance, allPagesContainer, 8192);
with this external signature container class
public class AllPagesSignatureContainer : IExternalSignatureContainer
{
public AllPagesSignatureContainer(PdfSignatureAppearance appearance, IExternalSignature externalSignature, ICollection<X509Certificate> chain)
{
this.appearance = appearance;
this.chain = chain;
this.externalSignature = externalSignature;
}
public void ModifySigningDictionary(PdfDictionary signDic)
{
signDic.Put(PdfName.FILTER, PdfName.ADOBE_PPKMS);
signDic.Put(PdfName.SUBFILTER, PdfName.ADBE_PKCS7_DETACHED);
PdfStamper stamper = appearance.Stamper;
PdfReader reader = stamper.Reader;
PdfDictionary xobject1 = new PdfDictionary();
PdfDictionary xobject2 = new PdfDictionary();
xobject1.Put(PdfName.N, appearance.GetAppearance().IndirectReference);
xobject2.Put(PdfName.AP, xobject1);
PdfIndirectReference PRef = stamper.Writer.PdfIndirectReference;
PdfLiteral PRefLiteral = new PdfLiteral((PRef.Number + 1 + 2*(reader.NumberOfPages - 1)) + " 0 R");
for (int i = 1; i < reader.NumberOfPages; i++)
{
var signatureField = PdfFormField.CreateSignature(stamper.Writer);
signatureField.Put(PdfName.T, new PdfString("ClientSignature_" + i.ToString()));
signatureField.Put(PdfName.V, PRefLiteral);
signatureField.Put(PdfName.F, new PdfNumber("132"));
signatureField.SetWidget(appearance.Rect, null);
signatureField.Put(PdfName.SUBTYPE, PdfName.WIDGET);
signatureField.Put(PdfName.AP, xobject1);
signatureField.SetPage();
Console.WriteLine(signatureField);
stamper.AddAnnotation(signatureField, i);
}
}
public byte[] Sign(Stream data)
{
String hashAlgorithm = externalSignature.GetHashAlgorithm();
PdfPKCS7 sgn = new PdfPKCS7(null, chain, hashAlgorithm, false);
IDigest messageDigest = DigestUtilities.GetDigest(hashAlgorithm);
byte[] hash = DigestAlgorithms.Digest(data, hashAlgorithm);
byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, null, null, CryptoStandard.CMS);
byte[] extSignature = externalSignature.Sign(sh);
sgn.SetExternalDigest(extSignature, null, externalSignature.GetEncryptionAlgorithm());
return sgn.GetEncodedPKCS7(hash, null, null, null, CryptoStandard.CMS);
}
PdfSignatureAppearance appearance;
ICollection<X509Certificate> chain;
IExternalSignature externalSignature;
}
The predicted indirect object number of the signature value in the line
PdfIndirectReference PRef = stamper.Writer.PdfIndirectReference;
PdfLiteral PRefLiteral = new PdfLiteral((PRef.Number + 1 + 2*(reader.NumberOfPages - 1)) + " 0 R");
strictly depends upon the use case being "exactly one signature field per page". For different use cases the estimate the prediction would differ.
I stress this here once again because e.g. the OP of this question did not take this into account when trying "to place multiple signatures on single page".
Another strict requirement for the object number prediction above is that the PdfStamper is created as above, i.e. not in append mode. If the signature is applied as an incremental update, i.e. in append mode, the lines above have to be replaced by
stamper.Writer.AddToBody(new PdfNull(), stamper.Writer.PdfIndirectReference, true);
PdfIndirectReference PRef = stamper.Writer.PdfIndirectReference;
PdfLiteral PRefLiteral = new PdfLiteral((PRef.Number + reader.NumberOfPages) + " 0 R");
This made a difference in the context of this question; the first line, adding an indirect null object to the PDF, is necessary to make sure that in case of PDFs with object streams the object stream object number has already been determined and does not slip between the next objects, resulting in an off-by-one error for our prediction.
Beware: While this procedure creates something which does not violate the letter of the PDF specifications (which only forbid the cases where the same field object is referenced from multiple pages, be it via the same or via distinct widgets), it clearly does violate its intent, its spirit. Thus, this procedure might also become forbidden as part of a Corrigenda document for the specification.
I'm trying to RSA encrypt an NSData using a public key. The public key is in this format:
<RSAKeyValue>
<Modulus>yOTe0L1/NcbXdZYwliS82MiTE8VD5WD23S4RDsdbJOFzCLbsyb4d+K1M5fC+xDfCkji1zQjPiiiToZ7JSj/2ww==</Modulus>
<Exponent>AWAB</Exponent>
</RSAKeyValue>
After extracting the modulus and exponent from the XML string, how do I get a SecKeyRef out of those to be used as publicKey in the method below?
+ (NSString *)encryptRSA:(NSString *)plainTextString key:(SecKeyRef)publicKey
{
size_t cipherBufferSize = SecKeyGetBlockSize(publicKey);
uint8_t *cipherBuffer = malloc(cipherBufferSize);
uint8_t *nonce = (uint8_t *)[plainTextString UTF8String];
SecKeyEncrypt(publicKey,
kSecPaddingOAEP,
nonce,
strlen( (char*)nonce ),
&cipherBuffer[0],
&cipherBufferSize);
NSData *encryptedData = [NSData dataWithBytes:cipherBuffer length:cipherBufferSize];
return [encryptedData base64EncodedString];
}
I can't seem to find a definite answer anywhere.
Wow, no wonder it's so hard to find an answer to this. I spent 2 days down the crypto-rabbit hole, and it's not pretty.
The easy way
Use Chilkat iOS RSA Library. One major downside: cost $189! :O
The hard way
Parse the XML, use SCZ-BasicEncodingRules-iOS to generate a public key data out of the modulus and exponent. If that works, create a dummy keychain using that public key (follow sample code here), extract the public key now in SecKeyRef format and pass it to the encryptRSA method in the question. Finally, cleanup, remove the dummy keychain. Sounds good in theory, but I have never tested this thoroughly, if you do, let me know!
I have used the below method for encryption using public key without using any third party libs, guess it may help who is looking for the same after they implemented it just as I did :D
+(NSString *)encryptRSA:(NSString *)plainTextString key:(SecKeyRef)publicKey
{
size_t cipherBufferSize = SecKeyGetBlockSize(publicKey);
uint8_t *cipherBuffer = malloc(cipherBufferSize);
uint8_t *nonce = (uint8_t *)[plainTextString UTF8String];
SecKeyEncrypt(publicKey,
kSecPaddingPKCS1,
nonce,
strlen( (char*)nonce ),
&cipherBuffer[0],
&cipherBufferSize);
NSData *encryptedData = [NSData dataWithBytes:cipherBuffer length:cipherBufferSize];
return [encryptedData base64EncodedStringWithOptions:0];
}
I think this will help u!
you can create a java file like fellow:
this java funtion will generate a public key to base64String
public static RSAPublicKey getPublicKey(String modulus, String exponent) {
try {
BigInteger b1 = new BigInteger(modulus,16);
BigInteger b2 = new BigInteger(exponent,16);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static String encodePublicKey(byte[] encoded) throws Exception{
BASE64Encoder base64Encoder= new BASE64Encoder();
String s=base64Encoder.encode(encoded);
return s;
u should use like :encodePublicKey(publicKey.getEncoded());
Got it!
I have my passwords encoded in MD5 in C# and inserted in my DB.
MD5 MD5Hasher = MD5.Create();
byte[] PasswordHash = MD5Hasher.ComputeHash(Encoding.Unicode.GetBytes(PasswordText.Value));
PasswordHash is inserted as is and look like 0x09C09E5B52580E477514FA.......... for example.
In the blackberry app, I get the password, want to encode it to pass it to a web service that will compare both hashed password. The problem is my result is different from the MD5 I create in my Blackberry app.
password = Crypto.encodeStringMD5(password);
Then below my function:
public static String encodeStringMD5(String s) throws Exception {
byte[] bytes = s.getBytes();
MD5Digest digest = new MD5Digest();
digest.update(bytes, 0, bytes.length);
int length = digest.getDigestLength();
byte[] md5 = new byte[length];
digest.getDigest(md5, 0, true);
return convertToHex(md5);
}
private static String convertToHex(byte[] data) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < data.length; i++) {
int halfbyte = (data[i] >>> 4) & 0x0F;
int two_halfs = 0;
do {
if ((0 <= halfbyte) && (halfbyte <= 9))
buf.append((char) ('0' + halfbyte));
else
buf.append((char) ('a' + (halfbyte - 10)));
halfbyte = data[i] & 0x0F;
} while(two_halfs++ < 1);
}
return buf.toString();
}
So it returns something like this: 07054da3aea1cc98377fe0..........
Any idea how I can get the same hashed password that I create with my C# function in the Blackberry?
Thank you!
The getBytes() method of java String returns a different encoding than the Encoding.Unicode in .NET. You need to specify unambiguous encoding algorithms. Use UTF-8 for both platforms and you should be ok. You can also try providing a charset name to the getBytes method on the Java side; try getBytes("UTF-16")
GregS answered your question directly; but as an aside I would recommend against having the client create the MD5 sum. If the server manages creating the MD5sum, you can further ensure that the password can't be reverse engineered (eg rainbow table) by adding a "salt" value to the password before encoding it on the server. If you do that on the client, you must expose the salt to the client which is less secure.
Do you check the format? Many languages create the same hashes but in different formats.
For example:
5f45r5ssfds544g56fd4gfd56g4f6dgf
vs.
5f-45-r5-ss-fd-s5-44-g5-6f-d4-gf-d5-6g-4f-6d-gf
Try checking for both formats when converting to a string.