AES Encryption/Decryption with Bouncycastle Example in J2ME - java-me

i want to Encrypt and Decrypt data in J2ME using AES Algorithm with bouncy castle
can any one give me sample code for that
i want to use ECB with PKCS5Padding
Thanks in Advance.

I'm sure there are examples out there but I haven't found them. Here are a few hints to help you get started. You need to learn how to connect the BC classes together. First, get the bouncycastle source code and be prepared to look at it when you have questions. It's actually very readable so don't be afraid to examine it when the documentation is poor. For example, many classes want an instance of a CipherParameters object, but it is rare for the documentation to specify any more detail. However, in the source code it will be obvious as to which implementing classes are expected.
Choose one of the AES engines, for example AESEngine, as the encryption engine. Next pick a mode; ECB is rarely correct, so for example if you pick CBC mode then create a CBCBlockCipher object from your AESEngine object. Next, use this object to create a PaddedBufferBlockCipher object. The default constructor uses PKCS7 padding which is identical to the PKCS5 padding you want. Now you need to create an object to hold the key and IV. This is the CipherParameters interface. You create the object in two steps. First, you create a KeyParameter object with your key. Next, you create a ParametersWithIV object with your KeyParameter object and your IV. This object is supplied to the init method of the PaddedBufferBlockCipher object and then your are ready to go.
EDIT
Here is small example:
private static byte[] cipherData(PaddedBufferedBlockCipher cipher, byte[] data)
throws Exception
{
int minSize = cipher.getOutputSize(data.length);
byte[] outBuf = new byte[minSize];
int length1 = cipher.processBytes(data, 0, data.length, outBuf, 0);
int length2 = cipher.doFinal(outBuf, length1);
int actualLength = length1 + length2;
byte[] result = new byte[actualLength];
System.arraycopy(outBuf, 0, result, 0, result.length);
return result;
}
private static byte[] decrypt(byte[] cipher, byte[] key, byte[] iv) throws Exception
{
PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new CBCBlockCipher(
new AESEngine()));
CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key), iv);
aes.init(false, ivAndKey);
return cipherData(aes, cipher);
}
private static byte[] encrypt(byte[] plain, byte[] key, byte[] iv) throws Exception
{
PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new CBCBlockCipher(
new AESEngine()));
CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key), iv);
aes.init(true, ivAndKey);
return cipherData(aes, plain);
}

Related

How to decrypt mp4 PKCS8 encoded file using private key in node js and crypto

I'm trying to decrypt a MP4 file that is encrypted using public key in pkcs8 format in Node JS and private key.
I tried this code:
var decrypted = crypto.privateDecrypt({ key: privateKey, padding: crypto.constants.RSA_PKCS1_PADDING }, buffer);
I'm getting the following error:
Error: error:0406506C:rsa routines:rsa_ossl_private_decrypt:data greater than mod len
I'm currently using this Java code that is working. I would like to swich to Node JS
final byte[] cekWrapped = Base64.getDecoder().decode(conn.getHeaderField("x-amz-meta-x-amz-key").getBytes());
final byte[] iv = Base64.getDecoder().decode(conn.getHeaderField("x-amz-meta-x-amz-iv").getBytes());
// Now we need to decrypt the envelope
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(DECRYPT_MODE, privateKey);
final byte[] decryptedSymmetricKeyBytes = cipher.doFinal(cekWrapped);
final SecretKeySpec cek = new SecretKeySpec(decryptedSymmetricKeyBytes, "AES");
// Once we have the symmetric master key, we can decrypt the contents
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
try {
cipher.init(DECRYPT_MODE, cek, new IvParameterSpec(iv));
} catch (final InvalidKeyException e) {
System.out.println(
"Invalid key exception. Please make sure that Java Cryptography Extensions with unlimited " +
"jurisdiction are installed");
}
try (final InputStream in = conn.getInputStream()) {
try (final CipherInputStream cis = new CipherInputStream(in, cipher)) {
try (final FileOutputStream fos = new FileOutputStream(destination.toFile())) {
byte[] b = new byte[1024];
int bytesRead;
while ((bytesRead = cis.read(b)) >= 0) {
fos.write(b, 0, bytesRead);
}
}
}
}
RSA uses the difficulty of factoring large semi-primes as it's trap-door function.
As part of the RSA crypto-system two primes are generated during public/private key creation.
We call the two primes p and q. They multiply to form n, which is the modulus (a semi-prime).
Although RSA can be used to to encrypt data directly (via c=m^e mod{n}), you cannot encrypt data larger than the modulus directly.
Therefore if you are using 2048-bit primes to generate n, you can only encrypt 4096-bits of information directly with the keys (in practice even a little less).
Instead, for large data you need to generate a random symmetric key and send it to your counterpart encrypting it with their RSA public key, and then use the agreed key with a symmetric cipher like AES-GCM or xSalsa20.
Really though, you should move to using ECDH over elliptic curves.
tldr: If you encrypt some data with RSA, where data.length > modulus.length, you're gonna get nonsense when you decrypt it.

How can I generate a valid ECDSA EC key pair?

I am trying to generate ECDSA key pair using SpongyCastle in Android.
This is the code:
static {
Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
}
public static KeyPair generate() {
ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("prime256v1");
KeyPairGenerator generator = KeyPairGenerator.getInstance("ECDSA", "SC");
generator.initialize(ecSpec, new SecureRandom());
KeyPair keyPair = g.generateKeyPair();
Log.i(TAG, "EC Pub Key generated: " + utils.bytesToHex(keyPair.getPublic().getEncoded()));
Log.i(TAG, "EC Private Key generated: " + utils.bytesToHex(keyPair.getPrivate().getEncoded()));
return generator.generateKeyPair();
}
Something is wrong since I always get something like that example of
Public Key:
3059301306072A8648CE3D020106082A8648CE3D03010703420004483ABA9F322240010ECF00E818C041A60FE71A2BD64C64CD5A60519985F110AEDE6308027D2730303F5E2478F083C7F5BB683DCAC22BFEB62F3A48BD01009F40
and Private Key:
308193020100301306072A8648CE3D020106082A8648CE3D030107047930770201010420219AB4B3701630973A4B2917D53F69A4BE6DAD61F48016BFEF147B2999575CB2A00A06082A8648CE3D030107A14403420004483ABA9F322240010ECF00E818C041A60FE71A2BD64C64CD5A60519985F110AEDE6308027D2730303F5E2478F083C7F5BB683DCAC22BFEB62F3A48BD01009F40
The site ECDSA sample give me "Invalid ECDSA signature message", and them seems really very different from that smaller Private Key and always starting with "04" Public Key generated in the same site.
Also, my backend verification gives me the error "Invalid point encoding 0x30"
The backend Java method check is:
public ECPublicKey getPublicKeyFromHex(String publicKeyHex)
throws NoSuchAlgorithmException, DecoderException, ApplicationGenericException {
byte[] rawPublicKey = Hex.decodeHex(publicKeyHex.toCharArray());
ECPublicKey ecPublicKey = null;
KeyFactory kf = null;
ECNamedCurveParameterSpec ecNamedCurveParameterSpec = ECNamedCurveTable.getParameterSpec("prime256v1");
ECCurve curve = ecNamedCurveParameterSpec.getCurve();
EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, ecNamedCurveParameterSpec.getSeed());
java.security.spec.ECPoint ecPoint = ECPointUtil.decodePoint(ellipticCurve, rawPublicKey);
java.security.spec.ECParameterSpec ecParameterSpec = EC5Util.convertSpec(ellipticCurve,
ecNamedCurveParameterSpec);
java.security.spec.ECPublicKeySpec publicKeySpec = new java.security.spec.ECPublicKeySpec(ecPoint,
ecParameterSpec);
kf = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider());
try {
ecPublicKey = (ECPublicKey) kf.generatePublic(publicKeySpec);
} catch (Exception e) {
throw new ApplicationGenericException(e.getMessage(), e.getCause());
}
return ecPublicKey;
}
Java's default encoding for a PublicKey is "X.509" which is not just the EC point; it is an ASN.1 structure identifying the algorithm (EC) and parameters (here prime256v1) PLUS a BIT STRING wrapping the point; see rfc5280 section 4.2.1.7 and rfc3279 section 2.3.5.
Similarly the default encoding for PrivateKey is "PKCS#8" (unencrypted) which is a structure containing an AlgorithmIdentifier plus an OCTET STRING wrapping the data which in this case contains both the private key value and a copy of the public key, see rfc5208 section 5 and C.4 of document SEC 1 at http://www.secg.org with tag [0] omitted but tag [1] present.
To read (either or both of) them back in to Java, get a KeyFactory.getInstance("EC") and use generate{Public,Private} on an X509EncodedKeySpec or PKCS8EncodedKeySpec respectively.
ECDSA and ECDH (and ECMQV etc) use the same key structures, unlike classic integer DSA and DH which use the same mathematical structure ($Z_p^*$) but slightly different representations.
PS: the javadoc for java.security.Key tells you most of this.
More practical example. Convert generated public key to decoded bytes array or hex string:
public String getPublicKeyAsHex(PublicKey publicKey){
ECPublicKey ecPublicKey = (ECPublicKey)publicKey;
ECPoint ecPoint = ecPublicKey.getW();
byte[] publicKeyBytes = new byte[PUBLIC_KEY_LENGTH];
writeToStream(publicKeyBytes, 0, ecPoint.getAffineX(), PRIVATE_KEY_LENGTH);
writeToStream(publicKeyBytes, PRIVATE_KEY_LENGTH, ecPoint.getAffineY(), PRIVATE_KEY_LENGTH);
String hex = Hex.toHexString(publicKeyBytes);
logger.debug("Public key bytes: " + Arrays.toString(publicKeyBytes));
logger.debug("Public key hex: " + hex);
return hex;
}
private void writeToStream(byte[] stream, int start, BigInteger value, int size) {
byte[] data = value.toByteArray();
int length = Math.min(size, data.length);
int writeStart = start + size - length;
int readStart = data.length - length;
System.arraycopy(data, readStart, stream, writeStart, length);
}
Convert decoded bytes array back to PublicKey:
KeyFactory factory = KeyFactory.getInstance(ALGORITHM, ALGORITHM_PROVIDER);
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(CURVE);
ECNamedCurveSpec params = new ECNamedCurveSpec(CURVE, spec.getCurve(), spec.getG(), spec.getN());
BigInteger xCoordinate = new BigInteger(1, Arrays.copyOfRange(decodedPublicKey, 0, PRIVATE_KEY_LENGTH));
BigInteger yCoordinate = new BigInteger(1, Arrays.copyOfRange(decodedPublicKey, PRIVATE_KEY_LENGTH, PUBLIC_KEY_LENGTH));
java.security.spec.ECPoint w = new java.security.spec.ECPoint(xCoordinate, yCoordinate);
PublicKey encodedPublicKey = factory.generatePublic(new java.security.spec.ECPublicKeySpec(w, params));

How to sign in using data from WebSecurity tables?

I want to sign users in with the standard WebSecurity tables; but in another language.
For example I have this ASP MVC website. I'm making an app using PHP now that has access to the same database, and I need to know how microsoft's password strategies work.
Here's an example of a table: http://gyazo.com/e55d76186472b17fe8f25481a3a3e1c9
I would guess it's just hash_password= hash(password . salt)
But which hashing does it use, etc etc.
Thanks a lot!
Well, reflector tells me that they use Crypto.HashPassword which looks like:
public static string HashPassword(string password)
{
byte[] salt;
byte[] buffer2;
if (password == null)
{
throw new ArgumentNullException("password");
}
using (System.Security.Cryptography.Rfc2898DeriveBytes bytes = new System.Security.Cryptography.Rfc2898DeriveBytes(password, 0x10, 0x3e8))
{
salt = bytes.Salt;
buffer2 = bytes.GetBytes(0x20);
}
byte[] dst = new byte[0x31];
Buffer.BlockCopy(salt, 0, dst, 1, 0x10);
Buffer.BlockCopy(buffer2, 0, dst, 0x11, 0x20);
return Convert.ToBase64String(dst);
}

J2ME AES Decryption Error(org.bouncycastle.crypto.InvalidCipherTextException: pad block corrupted)

I am doing encryption and decryption using AES Algorithm with bouncy castle
My encryption and decryption works ok but it gives me error when my plain text size is bigger
even sometimes it is giving non decrypted data
public static boolean setEncryptionKey(String keyText)
{
byte[] keyBytes = keyText.getBytes();
key = new KeyParameter(keyBytes);
engine = new AESFastEngine();
cipher = new PaddedBufferedBlockCipher(engine);
return true;
}
Encryption:
public static String encryptString(String plainText)
{
byte[] plainArray = plainText.getBytes();
cipher.init(true, key);
byte[] cipherBytes = new byte[cipher.getOutputSize(plainArray.length)];
int cipherLength = cipher.processBytes(plainArray, 0, plainArray.length, cipherBytes, 0);
cipher.doFinal(cipherBytes, cipherLength);
String cipherString = new String(cipherBytes);
return cipherString;
}
Decryption:
public static String decryptString(String encryptedText)
{
byte[] cipherBytes = encryptedText.getBytes();
cipher.init(false, key);
byte[] decryptedBytes = new byte[cipher.getOutputSize(cipherBytes.length)];
int decryptedLength = cipher.processBytes(cipherBytes, 0, cipherBytes.length, decryptedBytes, 0);
cipher.doFinal(decryptedBytes, decryptedLength);
String decryptedString = new String(decryptedBytes);
int index = decryptedString.indexOf("\u0000");
if (index >= 0)
{
decryptedString = decryptedString.substring(0, index);
}
return decryptedString;
}
This decryption is giving me following error
org.bouncycastle.crypto.InvalidCipherTextException: pad block corrupted
at org.bouncycastle.crypto.paddings.PKCS7Padding.padCount(+30)
at org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher.doFinal(+190)
at com.NewCrypto.decryptString(NewCrypto.java:103)
at com.New_Midlet.startApp(New_Midlet.java:23)
at javax.microedition.midlet.MIDletProxy.startApp(MIDletProxy.java:44)
at com.sun.midp.midlet.Scheduler.schedule(Scheduler.java:375)
at com.sun.midp.main.Main.runLocalClass(Main.java:477)
at com.sun.midp.main.Main.main(+80)
what could be the problem ?
The line
String cipherString = new String(cipherBytes);
is a bug. cipherBytes is a byte array with arbitrary values and cannot be converted to a string using any of the Java string decoders. You should just send/save the cipher as a byte array. If you must make it a string then you'll have to use an encoder. Base64 encoders are often used, as are Base16 (hex). You can use the Apache Commons Codec or my favorite, the Harder Base64 codec.

string message authentication

I get string messages from the clients which needs to be authenticated in the server.
I need to ensure that I (the server) got the exact string content which was sent by the client. I don't care about the client identity. Just the message.
I thought of using hashcode or CRC algorithm.
Do you have any suggestions/best practices for it?
Thanks a lot,
Adi Barda
To make certain the string is identical, then yes, a hash will do the job. The only problem you will encounter is that if the server has nothing to match to, all you will have is that the string you have is the same as the string that was hashed.
Any language you are using in particular?
Here's an example in C#, which hashes a string then converts into Base64:
public static string QHash(string str)
{
SHA512 SHA512HashCreator = SHA512.Create();
byte[] EncryptedData = SHA512HashCreator.ComputeHash(Encoding.UTF8.GetBytes(str));
StringBuilder qhash = new StringBuilder();
for (int i = 0; i < EncryptedData.Length; i++)
{
qhash.Append(EncryptedData[i].ToString("X2"));
}
return qhash.ToString().ToUpper();
}

Resources