Java tutorial
package org.ourfilesystem.security; /* OurFileSystem is a peer2peer file sharing program. Copyright (C) 2012 Robert Gass This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.security.SecureRandom; import java.util.Arrays; import java.util.Date; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.InvalidCipherTextException; import org.bouncycastle.crypto.digests.SHA512Digest; import org.bouncycastle.crypto.engines.AESEngine; import org.bouncycastle.crypto.engines.RSAEngine; import org.bouncycastle.crypto.generators.RSAKeyPairGenerator; import org.bouncycastle.crypto.modes.CBCBlockCipher; import org.bouncycastle.crypto.paddings.PKCS7Padding; import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.RSAKeyGenerationParameters; import org.bouncycastle.crypto.params.RSAKeyParameters; import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; import org.bouncycastle.crypto.encodings.PKCS1Encoding; import org.ourfilesystem.db.so.Network; import org.ourfilesystem.db.so.NetworkAuthorization; import org.ourfilesystem.db.so.Peer; import org.ourfilesystem.db.so.Post; import org.ourfilesystem.db.so.PostMessage; import org.ourfilesystem.db.so.PostTemplate; import org.ourfilesystem.db.so.PublicPost; import org.ourfilesystem.db.so.Subscribe; import org.ourfilesystem.utilities.BBytes; import org.ourfilesystem.utilities.ByteCounter; import org.ourfilesystem.utilities.FileUtils; public class SecurityTools { /* * SecureRandom should be thread safe. */ public static SecureRandom Random = new SecureRandom(); public static AsymmetricCipherKeyPair generateKeyPair() { /* * The probability that the new BigInteger represents a prime number will exceed (1 - 1/(2^certainty)) * 2^40 > 1T */ RSAKeyGenerationParameters parms = new RSAKeyGenerationParameters(BigInteger.valueOf(65537), // exponent Random, // Random generator 2048, // Key size 40); // Certainty RSAKeyPairGenerator gen = new RSAKeyPairGenerator(); gen.init(parms); return gen.generateKeyPair(); } public static KeySet generateKeySet() { AsymmetricCipherKeyPair encpair = SecurityTools.generateKeyPair(); AsymmetricCipherKeyPair signpair = SecurityTools.generateKeyPair(); KeySet ks = new KeySet(); ks.setPrivateEncryptionKey(encpair.getPrivate()); ks.setPrivateSigningKey(signpair.getPrivate()); PublicKeySet pub = new PublicKeySet(); pub.setPublicEncryptionKey(encpair.getPublic()); pub.setPublicSigningKey(signpair.getPublic()); ks.setPublicKeySet(pub); return ks; } public static void writeRSAPublicKey(RSAKeyParameters p, OutputStream fos, ByteCounter c) throws IOException { byte exp[] = p.getExponent().toByteArray(); byte mod[] = p.getModulus().toByteArray(); FileUtils.writeBytes(fos, exp, c); FileUtils.writeBytes(fos, mod, c); } public static RSAKeyParameters readRSAPublicKey(InputStream fis, ByteCounter c) throws IOException { byte[] exp = FileUtils.readBytes(fis, c); byte[] mod = FileUtils.readBytes(fis, c); RSAKeyParameters pub = new RSAKeyParameters(false, //boolean isPrivate, new BigInteger(mod), //java.math.BigInteger modulus, new BigInteger(exp)); //java.math.BigInteger exponent return pub; } public static void writeRSAPrivateKey(RSAPrivateCrtKeyParameters p, OutputStream fos, ByteCounter c) throws IOException { FileUtils.writeBytes(fos, p.getDP().toByteArray(), c); FileUtils.writeBytes(fos, p.getDQ().toByteArray(), c); FileUtils.writeBytes(fos, p.getExponent().toByteArray(), c); FileUtils.writeBytes(fos, p.getModulus().toByteArray(), c); FileUtils.writeBytes(fos, p.getP().toByteArray(), c); FileUtils.writeBytes(fos, p.getPublicExponent().toByteArray(), c); FileUtils.writeBytes(fos, p.getQ().toByteArray(), c); FileUtils.writeBytes(fos, p.getQInv().toByteArray(), c); } public static RSAPrivateCrtKeyParameters readRSAPrivateKey(InputStream fis, ByteCounter c) throws IOException { byte[] dp = FileUtils.readBytes(fis, c); byte[] dq = FileUtils.readBytes(fis, c); byte[] exp = FileUtils.readBytes(fis, c); byte[] mod = FileUtils.readBytes(fis, c); byte[] p = FileUtils.readBytes(fis, c); byte[] pe = FileUtils.readBytes(fis, c); byte[] q = FileUtils.readBytes(fis, c); byte[] qi = FileUtils.readBytes(fis, c); RSAPrivateCrtKeyParameters priv = new RSAPrivateCrtKeyParameters(new BigInteger(mod), //java.math.BigInteger modulus, new BigInteger(pe), //java.math.BigInteger publicExponent, new BigInteger(exp), //java.math.BigInteger privateExponent, new BigInteger(p), //java.math.BigInteger p, new BigInteger(q), //java.math.BigInteger q, new BigInteger(dp), //java.math.BigInteger dP, new BigInteger(dq), //java.math.BigInteger dQ, new BigInteger(qi)); //java.math.BigInteger qInv return priv; } public static void writePublicKeySet(PublicKeySet k, OutputStream fos, ByteCounter c) throws IOException { writeRSAPublicKey((RSAKeyParameters) k.getPublicEncryptionKey(), fos, c); writeRSAPublicKey((RSAKeyParameters) k.getPublicSigningKey(), fos, c); } public static PublicKeySet readPublicKeySet(InputStream fis, ByteCounter c) throws IOException { PublicKeySet p = new PublicKeySet(); p.setPublicEncryptionKey(readRSAPublicKey(fis, c)); p.setPublicSigningKey(readRSAPublicKey(fis, c)); return p; } public static void writeSignedDigest(SignedDigest s, OutputStream fos, ByteCounter c) throws IOException { FileUtils.writeBytes(fos, ((BBytes) s.getDigest()).getBytes(), c); if (s.getPeerIdentifier() == null) { fos.write(2); c.add(1); } else { fos.write(1); c.add(1); FileUtils.writeBytes(fos, ((BBytes) s.getPeerIdentifier()).getBytes(), c); } FileUtils.writeBytes(fos, ((BBytes) s.getSignature()).getBytes(), c); } public static SignedDigest readSignedDigest(InputStream fis, ByteCounter c) throws IOException { SignedDigest s = new SignedDigest(); s.setDigest(new BBytes(FileUtils.readBytes(fis, c))); int v = fis.read(); c.add(1); if (v == 2) { s.setPeerIdentifier(null); } else { s.setPeerIdentifier(new BBytes(FileUtils.readBytes(fis, c))); } s.setSignature(new BBytes(FileUtils.readBytes(fis, c))); return s; } public static void writeKeySet(KeySet k, OutputStream fos, ByteCounter c) throws IOException { writeRSAPrivateKey((RSAPrivateCrtKeyParameters) k.getPrivateEncryptionKey(), fos, c); writeRSAPrivateKey((RSAPrivateCrtKeyParameters) k.getPrivateSigningKey(), fos, c); writePublicKeySet(k.getPublicKeySet(), fos, c); } public static KeySet readKeySet(InputStream fis, ByteCounter c) throws IOException { KeySet k = new KeySet(); k.setPrivateEncryptionKey(readRSAPrivateKey(fis, c)); k.setPrivateSigningKey(readRSAPrivateKey(fis, c)); k.setPublicKeySet(readPublicKeySet(fis, c)); return k; } public static void DigestRSAPublicKey(Digest dig, RSAKeyParameters pub) { byte[] a = null; a = pub.getExponent().toByteArray(); dig.update(a, 0, a.length); a = pub.getModulus().toByteArray(); dig.update(a, 0, a.length); } public static byte[] digestPublicKey(PublicKeySet k) { SHA512Digest dig = new SHA512Digest(); DigestRSAPublicKey(dig, (RSAKeyParameters) k.getPublicEncryptionKey()); DigestRSAPublicKey(dig, (RSAKeyParameters) k.getPublicSigningKey()); byte sig[] = new byte[dig.getDigestSize()]; dig.doFinal(sig, 0); return sig; } public static void genIdentity(Peer p) { byte pdig[] = digestPublicKey(p.getPeerKeys()); BBytes pbb = new BBytes(pdig); p.setIdentity(pbb); } public static boolean verifyIdentity(Peer p) { byte pdig[] = digestPublicKey(p.getPeerKeys()); BBytes pbb = new BBytes(pdig); return pbb.equals(p.getIdentity()); } public static SignedDigest signDigest(byte dig[], BBytes peerid, RSAPrivateCrtKeyParameters key) { SignedDigest s = new SignedDigest(); RSAEngine eng = new RSAEngine(); byte pai[] = peerid.getBytes(); byte signblock[] = new byte[dig.length + pai.length]; System.arraycopy(dig, 0, signblock, 0, dig.length); System.arraycopy(pai, 0, signblock, dig.length, pai.length); PKCS1Encoding enc = new PKCS1Encoding(eng); enc.init(true, key); try { byte sig[] = enc.processBlock(signblock, 0, signblock.length); s.setDigest(new BBytes(dig)); s.setPeerIdentifier(peerid); s.setSignature(new BBytes(sig)); return s; } catch (InvalidCipherTextException e) { e.printStackTrace(); throw new RuntimeException(e.getMessage()); } } public static boolean verifySignedDigest(SignedDigest s, byte checkdig[], PublicKeySet pub) { if (!Arrays.equals(((BBytes) s.getDigest()).getBytes(), checkdig)) { return false; } RSAEngine eng = new RSAEngine(); PKCS1Encoding enc = new PKCS1Encoding(eng); enc.init(false, (CipherParameters) pub.getPublicSigningKey()); byte sig[] = ((BBytes) s.getSignature()).getBytes(); try { byte decsig[] = enc.processBlock(sig, 0, sig.length); byte encdig[] = new byte[checkdig.length]; System.arraycopy(decsig, 0, encdig, 0, encdig.length); byte encpeer[] = new byte[decsig.length - checkdig.length]; System.arraycopy(decsig, checkdig.length, encpeer, 0, encpeer.length); byte[] genpeer = digestPublicKey(pub); boolean signmatch = Arrays.equals(encdig, checkdig); boolean idmatch = Arrays.equals(genpeer, encpeer); return signmatch && idmatch; } catch (Exception e) { e.printStackTrace(); } return false; } public static BBytes digestFile(File f, long offset, long size) throws IOException { SHA512Digest d = new SHA512Digest(); digestFile(d, f, offset, size); byte sig[] = new byte[d.getDigestSize()]; d.doFinal(sig, 0); return new BBytes(sig); } public static void digestFile(Digest d, File f, long offset, long size) throws IOException { FileInputStream fis = new FileInputStream(f); fis.skip(offset); byte buf[] = new byte[1024]; int isize = Integer.MAX_VALUE; if (size < (long) isize) { isize = (int) size; } int len = fis.read(buf, 0, Math.min(buf.length, isize)); while (len != -1 && size > 0) { size -= len; if (len > 0) { d.update(buf, 0, len); } isize = Integer.MAX_VALUE; if (size < (long) isize) { isize = (int) size; } len = fis.read(buf, 0, Math.min(buf.length, isize)); } fis.close(); } public static void digestLong(Digest d, long val) { byte b[] = new byte[Long.SIZE / Byte.SIZE]; ByteBuffer buf = ByteBuffer.wrap(b); buf.putLong(val); d.update(b, 0, b.length); } public static void digestDouble(Digest d, double db) { byte b[] = new byte[Double.SIZE / Byte.SIZE]; ByteBuffer buf = ByteBuffer.wrap(b); buf.putDouble(db); d.update(b, 0, b.length); } public static void digestString(Digest d, String str) { if (str != null) { byte strb[] = str.getBytes(Charset.forName("UTF-16BE")); d.update(strb, 0, strb.length); } else { d.update((byte) 0); } } public static void digestBBytes(Digest d, BBytes b) { if (b != null) { byte bb[] = b.getBytes(); d.update(bb, 0, bb.length); } else { d.update((byte) 0); } } public static void digestBoolean(Digest d, boolean b) { if (b) { d.update((byte) 1); } else { d.update((byte) 0); } } public static void digestDate(Digest d, Date dt) { if (dt == null) { d.update((byte) 2); } else { d.update((byte) 1); digestLong(d, dt.getTime()); } } public static BBytes digestPeerLocation(Peer p) { SHA512Digest d = new SHA512Digest(); digestString(d, p.getIntroduction()); digestString(d, (String) p.getLocation()); digestString(d, (String) p.getNickname()); digestLong(d, p.getUpdateCount()); digestDate(d, p.getRDate()); byte id[] = p.getIdentity().getBytes(); d.update(id, 0, id.length); byte sig[] = new byte[d.getDigestSize()]; d.doFinal(sig, 0); return new BBytes(sig); } public static void digestPostTemplate(Digest d, PostTemplate p) { if (p == null) { d.update((byte) 2); } else { for (int c = 0; c < 10; c++) { String s = p.getBool(c); digestString(d, s); } for (int c = 0; c < 10; c++) { String s = p.getDouble(c); digestString(d, s); } for (int c = 0; c < 10; c++) { String s = p.getNum(c); digestString(d, s); } for (int c = 0; c < 3; c++) { String s = p.getRef(c); digestString(d, s); } for (int c = 0; c < 8; c++) { String s = p.getString(c); digestString(d, s); } digestString(d, p.getTemplateName()); digestString(d, p.getTemplateDescription()); } } public static void digestPostMessage(Digest d, PostMessage m) { if (m == null) { d.update((byte) 2); } else { d.update((byte) 1); digestString(d, m.getComment()); digestString(d, m.getString0()); digestString(d, m.getString1()); digestString(d, m.getString2()); digestString(d, m.getString3()); digestString(d, m.getString4()); digestString(d, m.getString5()); digestString(d, m.getString6()); digestString(d, m.getString7()); digestString(d, m.getFileName()); digestString(d, m.getSubject()); digestDouble(d, m.getDouble0()); digestDouble(d, m.getDouble1()); digestDouble(d, m.getDouble2()); digestDouble(d, m.getDouble3()); digestDouble(d, m.getDouble4()); digestDouble(d, m.getDouble5()); digestDouble(d, m.getDouble6()); digestDouble(d, m.getDouble7()); digestDouble(d, m.getDouble8()); digestDouble(d, m.getDouble9()); digestLong(d, m.getNum0()); digestLong(d, m.getNum1()); digestLong(d, m.getNum2()); digestLong(d, m.getNum3()); digestLong(d, m.getNum4()); digestLong(d, m.getNum5()); digestLong(d, m.getNum6()); digestLong(d, m.getNum7()); digestLong(d, m.getNum8()); digestLong(d, m.getNum9()); digestBBytes(d, m.getRef0()); digestBBytes(d, m.getRef1()); digestBBytes(d, m.getRef2()); digestBBytes(d, m.getUseTemplate()); digestBoolean(d, m.isBool0()); digestBoolean(d, m.isBool1()); digestBoolean(d, m.isBool2()); digestBoolean(d, m.isBool3()); digestBoolean(d, m.isBool4()); digestBoolean(d, m.isBool5()); digestBoolean(d, m.isBool6()); digestBoolean(d, m.isBool7()); digestBoolean(d, m.isBool8()); digestBoolean(d, m.isBool9()); } } public static BBytes digestPost(Post p, BBytes peerid) { SHA512Digest d = new SHA512Digest(); digestBBytes(d, p.getFileReferenceDigest()); digestBBytes(d, p.getNetworkId()); digestLong(d, p.getPostNumber()); if (p.getMessage() != null && p.getMessage() instanceof PostMessage) { PostMessage pm = (PostMessage) p.getMessage(); digestPostMessage(d, pm); } else if (p.getMessage() != null && p.getMessage() instanceof PostTemplate) { PostTemplate pt = (PostTemplate) p.getMessage(); digestPostTemplate(d, pt); } else if (p.getMessage() == null) { d.update((byte) 0); } else { throw new RuntimeException("Unknown message type!"); } digestBoolean(d, p.isPosterHasFile()); digestBBytes(d, peerid); digestDate(d, p.getRDate()); byte sig[] = new byte[d.getDigestSize()]; d.doFinal(sig, 0); return new BBytes(sig); } public static BBytes digestPublicPost(PublicPost p, BBytes peerid) { SHA512Digest d = new SHA512Digest(); digestBBytes(d, p.getNetworkId()); digestLong(d, p.getPostNumber()); digestBoolean(d, p.isEncrypted()); if (p.getMessage() instanceof BBytes) { BBytes mb = (BBytes) p.getMessage(); digestBBytes(d, mb); } else { String str = (String) p.getMessage(); digestString(d, str); } digestBBytes(d, peerid); digestDate(d, p.getRDate()); byte sig[] = new byte[d.getDigestSize()]; d.doFinal(sig, 0); return new BBytes(sig); } public static BBytes digestSubscribe(Subscribe s, BBytes peerid) { SHA512Digest d = new SHA512Digest(); digestBBytes(d, s.getNetworkID()); digestDate(d, s.getRDate()); digestLong(d, s.getSubNumber()); digestBBytes(d, peerid); digestBoolean(d, s.isSubscribe()); byte sig[] = new byte[d.getDigestSize()]; d.doFinal(sig, 0); return new BBytes(sig); } public static void signSubscriber(Subscribe s, BBytes peerid, RSAPrivateCrtKeyParameters key) { BBytes dig = digestSubscribe(s, peerid); s.setSignature(signDigest(dig.getBytes(), peerid, key)); } public static boolean verifySubscriber(Subscribe s, PublicKeySet pub) { BBytes dig = digestSubscribe(s, s.getSignature().getPeerIdentifier()); return verifySignedDigest(s.getSignature(), dig.getBytes(), pub); } public static BBytes digestNetwork(Network n, BBytes peerid) { SHA512Digest d = new SHA512Digest(); digestString(d, n.getDescription()); digestLong(d, n.getNetworkNumber()); digestString(d, n.getTitle()); digestBBytes(d, peerid); digestDate(d, n.getRDate()); if (n.getPublic() != null) { digestBoolean(d, n.getPublic()); } byte sig[] = new byte[d.getDigestSize()]; d.doFinal(sig, 0); return new BBytes(sig); } public static void signNetwork(Network n, BBytes peerid, RSAPrivateCrtKeyParameters key) { BBytes dig = digestNetwork(n, peerid); n.setSignature(signDigest(dig.getBytes(), peerid, key)); } public static boolean verifyNetwork(Network n, PublicKeySet pub) { BBytes dig = digestNetwork(n, n.getSignature().getPeerIdentifier()); return verifySignedDigest(n.getSignature(), dig.getBytes(), pub); } public static void signPublicPost(PublicPost p, BBytes peerid, RSAPrivateCrtKeyParameters key) { BBytes dig = digestPublicPost(p, peerid); p.setSignature(signDigest(dig.getBytes(), peerid, key)); } public static boolean verifyPublicPost(PublicPost p, PublicKeySet pub) { BBytes dig = digestPublicPost(p, (BBytes) p.getSignature().getPeerIdentifier()); return verifySignedDigest(p.getSignature(), dig.getBytes(), pub); } public static void signPost(Post p, BBytes peerid, RSAPrivateCrtKeyParameters key) { BBytes dig = digestPost(p, peerid); p.setSignedDigest(signDigest(dig.getBytes(), peerid, key)); } public static boolean verifyPost(Post p, PublicKeySet pub) { BBytes dig = digestPost(p, (BBytes) p.getSignedDigest().getPeerIdentifier()); return verifySignedDigest(p.getSignedDigest(), dig.getBytes(), pub); } public static boolean verifyPeerIdentity(Peer p) { byte cdig[] = digestPublicKey(p.getPeerKeys()); return Arrays.equals(cdig, p.getIdentity().getBytes()); } public static void signNetworkAuth(NetworkAuthorization a, BBytes peerid, RSAPrivateCrtKeyParameters key) { SHA512Digest d = new SHA512Digest(); byte b[] = a.getNetworkId().getBytes(); d.update(b, 0, b.length); b = a.getPeerId().getBytes(); d.update(b, 0, b.length); digestLong(d, a.getSignatureNumber()); digestDate(d, a.getRDate()); byte sig[] = new byte[d.getDigestSize()]; d.doFinal(sig, 0); a.setSignature(signDigest(sig, peerid, key)); } public static boolean verifyNetworkAuth(NetworkAuthorization a, PublicKeySet pub) { SHA512Digest d = new SHA512Digest(); byte b[] = a.getNetworkId().getBytes(); d.update(b, 0, b.length); b = a.getPeerId().getBytes(); d.update(b, 0, b.length); digestLong(d, a.getSignatureNumber()); digestDate(d, a.getRDate()); byte sig[] = new byte[d.getDigestSize()]; d.doFinal(sig, 0); return verifySignedDigest(a.getSignature(), sig, pub); } public static void signPeerLocation(Peer p, RSAPrivateCrtKeyParameters key) { BBytes dig = SecurityTools.digestPeerLocation(p); SignedDigest sg = SecurityTools.signDigest(dig.getBytes(), p.getIdentity(), (RSAPrivateCrtKeyParameters) key); p.setLocationSignature(sg); } public static boolean verifyPeerLocation(Peer p, PublicKeySet key) { BBytes dig = SecurityTools.digestPeerLocation(p); return verifySignedDigest(p.getLocationSignature(), dig.getBytes(), key); } public static String decodePublicPost(BBytes enc, RSAPrivateCrtKeyParameters key) { try { byte encdata[] = enc.getBytes(); //Extract the header ByteBuffer bbuf = ByteBuffer.wrap(encdata); int headlen = bbuf.getInt(); if (headlen > 4096) { throw new Exception("Header is too long: " + headlen); } byte head[] = new byte[headlen]; System.arraycopy(encdata, Integer.SIZE / Byte.SIZE, head, 0, headlen); //Decode the header RSAEngine eng = new RSAEngine(); PKCS1Encoding eng2 = new PKCS1Encoding(eng); eng2.init(false, key); byte dechead[] = eng2.processBlock(head, 0, head.length); if (dechead.length < (2 * Long.SIZE / Byte.SIZE)) { //Magic number can't be there, not enough data. return null; } ByteBuffer mbuf = ByteBuffer.wrap(dechead); long m0 = mbuf.getLong(); long m1 = mbuf.getLong(); if (m0 != 0x01234567) { return null; } if (m1 != 0x76543210) { return null; } //Exctract the symmetric key. byte skey[] = new byte[dechead.length - (2 * Long.SIZE / Byte.SIZE)]; System.arraycopy(dechead, 2 * Long.SIZE / Byte.SIZE, skey, 0, skey.length); KeyParameter kp = new KeyParameter(skey); CBCBlockCipher aes = new CBCBlockCipher(new AESEngine()); PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(aes, new PKCS7Padding()); cipher.init(false, kp); int foffset = (Integer.SIZE / Byte.SIZE) + headlen; int enclen = encdata.length - foffset; byte[] output = new byte[cipher.getOutputSize(enclen)]; int len = cipher.processBytes(encdata, foffset, enclen, output, 0); int len2 = cipher.doFinal(output, len); byte rawdata[] = new byte[len + len2]; System.arraycopy(output, 0, rawdata, 0, rawdata.length); return new String(rawdata, Charset.forName("UTF-16BE")); } catch (Exception e) { //e.printStackTrace(); } return null; } public static BBytes encodePublicPost(String raw, PublicKeySet pubkey) { try { byte strb[] = raw.getBytes(Charset.forName("UTF-16BE")); byte[] key = new byte[32]; Random.nextBytes(key); KeyParameter kp = new KeyParameter(key); CBCBlockCipher aes = new CBCBlockCipher(new AESEngine()); PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(aes, new PKCS7Padding()); cipher.init(true, kp); byte[] output = new byte[cipher.getOutputSize(strb.length)]; int len = cipher.processBytes(strb, 0, strb.length, output, 0); cipher.doFinal(output, len); RSAEngine eng = new RSAEngine(); byte headblk[] = new byte[(2 * Long.SIZE / Byte.SIZE) + key.length]; ByteBuffer bbuf = ByteBuffer.wrap(headblk); bbuf.putLong(0x01234567); //magic number bbuf.putLong(0x76543210); //magic number System.arraycopy(key, 0, headblk, (2 * Long.SIZE / Byte.SIZE), key.length); PKCS1Encoding enc = new PKCS1Encoding(eng); enc.init(true, (CipherParameters) pubkey.getPublicEncryptionKey()); byte enchead[] = enc.processBlock(headblk, 0, headblk.length); byte rslt[] = new byte[(Integer.SIZE / Byte.SIZE) + enchead.length + output.length]; ByteBuffer rbuf = ByteBuffer.wrap(rslt); rbuf.putInt(enchead.length); System.arraycopy(enchead, 0, rslt, Integer.SIZE / Byte.SIZE, enchead.length); System.arraycopy(output, 0, rslt, (Integer.SIZE / Byte.SIZE) + enchead.length, output.length); BBytes orslt = new BBytes(rslt); return orslt; } catch (Exception e) { e.printStackTrace(); } return null; } }