From 386fdd6a8f26f8ac3414e917bf0551f7910eb0fc Mon Sep 17 00:00:00 2001 From: buddygr Date: Fri, 26 Aug 2022 22:51:08 +0800 Subject: [PATCH] =?UTF-8?q?1.=E4=BF=AE=E5=A4=8D=E5=B9=B6=E5=8D=87=E7=BA=A7?= =?UTF-8?q?1=E4=B8=AASL4A=E5=87=BD=E6=95=B0=EF=BC=9AscanBarcode(title=3DNo?= =?UTF-8?q?ne)=EF=BC=8C=E5=8F=AF=E4=BB=A5=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E6=A0=87=E9=A2=98=E5=92=8C=E5=BC=80=E5=85=B3=E9=97=AA=E5=85=89?= =?UTF-8?q?=E7=81=AF=E7=9A=84=E4=BA=8C=E7=BB=B4=E7=A0=81=E6=89=AB=E6=8F=8F?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E3=80=82=202.=E6=96=B0=E5=A2=9E11=E4=B8=AA?= =?UTF-8?q?=E5=8A=A0=E8=A7=A3=E5=AF=86=E7=9B=B8=E5=85=B3SL4A=E5=87=BD?= =?UTF-8?q?=E6=95=B0=EF=BC=9A=20=20=20cipherInit(=20key,=20algorithm=20=3D?= =?UTF-8?q?=20"AES/CBC/PKCS5Padding",=20encodingFormat=20=3D=20"",=20initi?= =?UTF-8?q?alVector=20=3D=20""=20)=EF=BC=8C=E5=8A=A0=E8=A7=A3=E5=AF=86?= =?UTF-8?q?=E5=BC=95=E6=93=8E=E5=88=9D=E5=A7=8B=E5=8C=96=E3=80=82=20=20=20?= =?UTF-8?q?encryptString(=20srcString=20)=20/=20decryptString(=20srcString?= =?UTF-8?q?=20)=EF=BC=8C=E5=8A=A0=E8=A7=A3=E5=AF=86=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E4=B8=B2=E3=80=82=20=20=20encryptStringToFile(=20srcString,=20?= =?UTF-8?q?dstFile=20)=20/=20decryptFileToString(=20srcFile=20)=EF=BC=8C?= =?UTF-8?q?=E5=8A=A0=E5=AF=86=E5=AD=97=E7=AC=A6=E4=B8=B2=E5=88=B0=E6=96=87?= =?UTF-8?q?=E4=BB=B6/=E8=A7=A3=E5=AF=86=E6=96=87=E4=BB=B6=E5=88=B0?= =?UTF-8?q?=E5=AD=97=E7=AC=A6=E4=B8=B2=E3=80=82=20=20=20encryptBytes(=20sr?= =?UTF-8?q?cBytes=20)=20/=20decryptBytes(=20srcBytes=20)=EF=BC=8C=E5=8A=A0?= =?UTF-8?q?=E8=A7=A3=E5=AF=86=E5=AD=97=E8=8A=82=E4=B8=B2=E3=80=82=20=20=20?= =?UTF-8?q?encryptBytesToFile(=20srcBytes,=20dstFile=20)=20/=20decryptFile?= =?UTF-8?q?ToBytes(=20srcFile=20)=EF=BC=8C=E5=8A=A0=E5=AF=86=E5=AD=97?= =?UTF-8?q?=E8=8A=82=E4=B8=B2=E5=88=B0=E6=96=87=E4=BB=B6/=E8=A7=A3?= =?UTF-8?q?=E5=AF=86=E6=96=87=E4=BB=B6=E5=88=B0=E5=AD=97=E8=8A=82=E4=B8=B2?= =?UTF-8?q?=E3=80=82=20=20=20encryptFile(=20srcFile,=20dstFile=20)=20/=20d?= =?UTF-8?q?ecryptFile(=20srcFile,=20dstFile=20)=EF=BC=8C=E5=8A=A0=E8=A7=A3?= =?UTF-8?q?=E5=AF=86=E6=96=87=E4=BB=B6=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qsl4a/qsl4a/facade/CipherFacade.java | 215 ++++++++++++++++++ .../qsl4a/facade/CommonIntentsFacade.java | 18 +- .../qsl4a/facade/FacadeConfiguration.java | 1 + 3 files changed, 230 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/qpython/qsl4a/qsl4a/facade/CipherFacade.java diff --git a/src/main/java/org/qpython/qsl4a/qsl4a/facade/CipherFacade.java b/src/main/java/org/qpython/qsl4a/qsl4a/facade/CipherFacade.java new file mode 100644 index 0000000..1dcf35b --- /dev/null +++ b/src/main/java/org/qpython/qsl4a/qsl4a/facade/CipherFacade.java @@ -0,0 +1,215 @@ +package org.qpython.qsl4a.qsl4a.facade; + +import android.app.Service; +import android.content.pm.PackageManager; +import android.util.Base64; + +import org.qpython.qsl4a.qsl4a.jsonrpc.RpcReceiver; +import org.qpython.qsl4a.qsl4a.rpc.Rpc; +import org.qpython.qsl4a.qsl4a.rpc.RpcDefault; +import org.qpython.qsl4a.qsl4a.rpc.RpcParameter; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +public class CipherFacade extends RpcReceiver { + + private final Service mService; + private final PackageManager mPackageManager; + //加密引擎 + private Cipher cipherEncrypt; + //解密引擎 + private Cipher cipherDecrypt; + //字符串编码 + private String EncodingFormat; + public static final int MAX_BUFFER_SIZE = 5242848;//max buffer size (5MB-32B) + + public CipherFacade(FacadeManager manager) { + super(manager); + mService = manager.getService(); + mPackageManager = mService.getPackageManager(); + } + + private static byte[] readFromFile(String filePath) { + try { + File file = new File(filePath); + FileInputStream fis = new FileInputStream(file); + int length = fis.available(); + byte[] data = new byte[length]; + fis.read(data); + fis.close(); + return data; + } catch (Exception e) { + e.printStackTrace(); + return new byte[0]; + }} + + private static void writeToFile(String filePath, byte[] data) { + try { + FileOutputStream fos = new FileOutputStream(filePath); + fos.write(data); + fos.flush(); + fos.close(); + } catch (Exception e) {e.printStackTrace();}} + + /** + * @function cipherInit 加密解密引擎设置 + * @params key 密钥 + * @params algorithm 加密算法(默认为AES/CBC/PKCS5Padding) + * @params encodingFormat 字符串编码格式(默认为空白(Base64),也可为UTF-8,GBK) + * @params initialVector 初始向量(CBC模式时使用) + */ + @Rpc(description = "Initialize Encrypt Engine / Decrypt Engine .") + public void cipherInit( + @RpcParameter(name = "key") final String key, + @RpcParameter(name = "algorithm") @RpcDefault("AES/CBC/PKCS5Padding") final String algorithm, + @RpcParameter(name = "encodingFormat") @RpcDefault("") final String encodingFormat, + @RpcParameter(name = "initialVector") @RpcDefault("") final String initialVector ) throws Exception { + cipherEncrypt = Cipher.getInstance(algorithm); + cipherDecrypt = Cipher.getInstance(algorithm); + byte[] Key; + byte[] InitialVector; + EncodingFormat = encodingFormat.toUpperCase(); + if (EncodingFormat.equals("")) { + //Base64解码 + Key = Base64.decode( key, Base64.DEFAULT ); + if (initialVector.equals("")) { + InitialVector = Key; + } else { + InitialVector = Base64.decode( initialVector, Base64.DEFAULT ); + } + } else { + //其他字符串编码解码 + Key = key.getBytes( encodingFormat ); + if (initialVector.equals("")) { + InitialVector = Key; + } else { + InitialVector = initialVector.getBytes(encodingFormat); + } + /*if (InitialVector.length > 16){ + byte[] IV = {}; + System.arraycopy(InitialVector,0,IV,0,16); + InitialVector = IV; + }*/ + } + //Algorithm 加密算法如AES + String Algorithm; + int pos = algorithm.indexOf("/"); + if ( pos == -1 ) { + Algorithm = algorithm; + } + else { + Algorithm = algorithm.substring( 0, pos ); + } + SecretKeySpec keySpec = new SecretKeySpec(Key, Algorithm); + //使用CBC模式,需要一个向量iv,可增加加密算法的强度 + IvParameterSpec iv = new IvParameterSpec(InitialVector); + if (algorithm.contains("CBC")) { + cipherEncrypt.init(Cipher.ENCRYPT_MODE, keySpec, iv); + cipherDecrypt.init(Cipher.DECRYPT_MODE, keySpec, iv); + } else {//ECB模式 + cipherEncrypt.init(Cipher.ENCRYPT_MODE, keySpec); + cipherDecrypt.init(Cipher.DECRYPT_MODE, keySpec); + } + } + + @Override + public void shutdown() { + } + + /** 全字符串传输模式 */ + + @Rpc(description = "Encrypt a Normal / Base64 String to another Base64 String .") + public String encryptString( + @RpcParameter(name = "srcString") final String srcString) + throws Exception { + byte[] rst; + if (EncodingFormat.equals("")) { + rst = Base64.decode( srcString, Base64.DEFAULT ); + } else { + rst = srcString.getBytes( EncodingFormat ); + } + return Base64.encodeToString( + cipherEncrypt.doFinal( rst ) + , Base64.DEFAULT); + } + + @Rpc(description = "Decrypt a Base64 String to another Normal / Base64 String .") + public String decryptString( + @RpcParameter(name = "srcString") final String srcString) + throws Exception { + byte[] rst = cipherDecrypt.doFinal( Base64.decode( srcString, Base64.DEFAULT )); + if (EncodingFormat.equals("")) { + return Base64.encodeToString( rst, Base64.DEFAULT ); + } else { + return new String( rst, EncodingFormat ); + } + } + + /** 半字符串半文件模式 */ + + @Rpc(description = "Encrypt a Normal / Base64 String to another File .") + public void encryptStringToFile( + @RpcParameter(name = "srcString") final String srcString, + @RpcParameter(name = "dstFile") final String dstFile) + throws Exception { + byte[] rst; + if (EncodingFormat.equals("")) { + rst = Base64.decode( srcString, Base64.DEFAULT ); + } else { + rst = srcString.getBytes( EncodingFormat ); + } + writeToFile( dstFile , + cipherEncrypt.doFinal( rst )); + } + + @Rpc(description = "Decrypt a File to another Normal / Base64 String .") + public String decryptFileToString( + @RpcParameter(name = "srcFile") final String srcFile) + throws Exception { + byte[] rst = cipherDecrypt.doFinal( readFromFile( srcFile )); + if (EncodingFormat.equals("")) { + return Base64.encodeToString( rst, Base64.DEFAULT ); + } else { + return new String( rst, EncodingFormat ); + } + } + + /** 全二进制文件模式 */ + + private void cipherFile(final String srcFile,final String dstFile,final Cipher cipher) + throws Exception { + FileInputStream fis = new FileInputStream(srcFile); + FileOutputStream fos = new FileOutputStream(dstFile); + int len = fis.available(); + if (len>MAX_BUFFER_SIZE) len=MAX_BUFFER_SIZE; //max buffer size 5MB + byte[] data = new byte[len]; + while((len=fis.read(data))==MAX_BUFFER_SIZE) + fos.write(cipher.update(data)); + fos.write(cipher.doFinal(data,0,len)); + fos.flush(); + fis.close(); + fos.close(); + } + + @Rpc(description = "Encrypt a File to another File .") + public void encryptFile( + @RpcParameter(name = "srcFile") final String srcFile, + @RpcParameter(name = "dstFile") final String dstFile) + throws Exception { + cipherFile(srcFile,dstFile,cipherEncrypt); + } + + @Rpc(description = "Decrypt a File to another File .") + public void decryptFile( + @RpcParameter(name = "srcFile") final String srcFile, + @RpcParameter(name = "dstFile") final String dstFile) + throws Exception { + cipherFile(srcFile,dstFile,cipherDecrypt); + } +} \ No newline at end of file diff --git a/src/main/java/org/qpython/qsl4a/qsl4a/facade/CommonIntentsFacade.java b/src/main/java/org/qpython/qsl4a/qsl4a/facade/CommonIntentsFacade.java index a8aad2d..f0baf0d 100644 --- a/src/main/java/org/qpython/qsl4a/qsl4a/facade/CommonIntentsFacade.java +++ b/src/main/java/org/qpython/qsl4a/qsl4a/facade/CommonIntentsFacade.java @@ -53,10 +53,20 @@ public class CommonIntentsFacade extends RpcReceiver { return mAndroidFacade.startActivityForResult(Intent.ACTION_PICK, uri, null, null, null, null); } - @Rpc(description = "Starts the barcode scanner.", returns = "A Map representation of the result Intent.") - public Intent scanBarcode() throws JSONException { - return mAndroidFacade.startActivityForResult("com.google.zxing.client.android.SCAN", null, - null, null, null, null); + @Rpc(description = "Starts the barcode scanner.", returns = "Scan Result String .") + public String scanBarcode( + @RpcParameter(name = "title") @RpcOptional String title + ) throws Exception { + Intent intent = new Intent(); + intent.setClassName(mService.getPackageName(),"org.qpython.qpy.main.activity.QrCodeActivityRstOnly"); + intent.setAction(Intent.ACTION_VIEW); + intent.putExtra("title",title); + intent = mAndroidFacade.startActivityForResult(intent); + try { + return intent.getStringExtra("result"); } + catch (NullPointerException e) { + return null; + } } private void view(Uri uri, String type) { diff --git a/src/main/java/org/qpython/qsl4a/qsl4a/facade/FacadeConfiguration.java b/src/main/java/org/qpython/qsl4a/qsl4a/facade/FacadeConfiguration.java index 422414e..7328ca5 100644 --- a/src/main/java/org/qpython/qsl4a/qsl4a/facade/FacadeConfiguration.java +++ b/src/main/java/org/qpython/qsl4a/qsl4a/facade/FacadeConfiguration.java @@ -90,6 +90,7 @@ public class FacadeConfiguration { sFacadeClassList.add(USBHostSerialFacade.class); sFacadeClassList.add(VideoFacade.class); sFacadeClassList.add(FloatViewFacade.class); + sFacadeClassList.add(CipherFacade.class); //if (sSdkLevel >= 4) { sFacadeClassList.add(TextToSpeechFacade.class); -- Gitee