Why is Java AWSKMS client decryption so much slower than Python boto3? - java

In my Java lambda, during cold start I want to decrypt passwords from environment variables. I'm using the AWSKMS client to decrypt a string (following examples from here), and I find it takes up to 2 seconds the first time I do this. In contrast, I have some code in python using boto3 which is doing the same thing and it runs in under 100ms. So clearly there's something wrong with my Java code. Here is the Java code with comments showing the 2 calls that together add up to nearly 2 seconds:
ByteBuffer ciphertextBlob = ByteBuffer.wrap(Base64.getDecoder().decode(encrValue));
DecryptRequest req = new DecryptRequest().withCiphertextBlob(ciphertextBlob);
AWSKMS kmsClient = AWSKMSClientBuilder.defaultClient(); // This call takes 800+ ms
ByteBuffer plainText = kmsClient.decrypt(req).getPlaintext(); // This call takes 900+ ms
String plainTextStr = StringUtils.stripToNull(StandardCharsets.UTF_8.decode(plainText).toString());
And here's the equivalent python code:
plainTextStr = boto3.client('kms').decrypt(CiphertextBlob=b64decode(encrValue))['Plaintext'].decode()
Clearly I'm doing something wrong in the Java code, but I can't find a simpler example of how to do it in Java.

Related

Google Protocol Buffers not reading properly

I am just setting up a new Java project which will (maybe, not so sure now) make use of Google Protocol Buffers. I am new to this API, so I started with a very basic test. A test whose outcome, to be honest, really disappointed me. Why isn't this very straight-forward code working?
var output = new ByteArrayOutputStream();
Message.Echo.newBuilder().setMsg("MSG1?").build().writeTo(output);
System.out.println("output.length " + output.toByteArray().length);
Message.Echo.newBuilder().setMsg("MSG2!!").build().writeTo(output);
System.out.println("output.length " + output.toByteArray().length);
var input = new ByteArrayInputStream(output.toByteArray());
System.out.println("input.available " + input.available());
System.out.print(Message.Echo.parseFrom(input));
System.out.println("input.available " + input.available());
System.out.print(Message.Echo.parseFrom(input));
The above code produces the following output:
output.length 7
output.length 15
input.available 15
msg: "MSG2!!"
input.available 0
It entirely misses the first messages, or rather it seems to "overwrite" it in some way since all the 15 bytes get read. Plus it fails to block on the second call considering there are no further bytes to read.
However, changing the two reading lines into:
System.out.print(Message.Echo.parseFrom(input.readNBytes(7)));
System.out.print(Message.Echo.parseFrom(input.readNBytes(15-7)));
correctly prints the two messages. I am running Kubuntu 18.04 with JDK 11. Am I missing something really important (not mentioned in the official tutorial) or is this a bug?
This is the .proto file:
syntax = "proto3";
package ...;
option java_package = "...";
option java_outer_classname = "Message";
message Echo {
string msg = 1;
}
Ok, it seems that in order to write/read multiple message using the same set of streams requires using writeDelimitedTo and parseDelimitedFrom instead, because parseFrom reads until reaching reaches EOF.
It seems that the preferred behaviour is to use a new Socket for each message. It sounds a bit odd to me, but I am sure there are good reason behind this. It should be better explained in the official tutorial though.

Creating an NDEF WiFi record using application/vnd.wfa.wsc in Android

As of Android 5.0.0 you can long tap on a WiFi connection and write that connection to a tag ("Write to NFC tag"). You can find the source for that operation here: WriteWifiConfigToNfcDialog.java. The relevant line that takes a WiFi connection and creates an NDEF payload appears to be here:
String wpsNfcConfigurationToken = mWifiManager.getWpsNfcConfigurationToken(mAccessPoint.networkId);
mWifiManager is an instance of WifiManager, however getWpsNfcConfigurationToken is not part of the API. By tracking down this method, we can find its commit here: Add calls for NFC WSC token creation which is unfortunately no help. This is where my investigation has run out. Edit:
I've found out the following call stack:
WifiServiceImpl.java calls mWifiStateMachine.syncGetWpsNfcConfigurationToken(netId);
WifiStateMachine.java calls mWifiNative.getNfcWpsConfigurationToken(netId);
WifiNative.java finally has the method
public String getNfcWpsConfigurationToken(int netId) {
return doStringCommand("WPS_NFC_CONFIG_TOKEN WPS " + netId);
}
which then calls
String result = doStringCommandNative(mInterfacePrefix + command);
where doStringCommandNative makes a system call (can't find the code for this anywhere).
Which is now where the investigation ends.
Hoping someone can step in and show me a method that creates an NdefRecord that is of the type application/vnd.wfa.wsc given an SSID, Password, Encryption/Auth type.
I've of course inspected the bytes of an actual application/vnd.wfa.wsc record created by Android but manually recreating this process with the bytes seems potentially very unreliable and is incredibly tedious.
The answer lies in the Wi-Fi Alliance "Wi-Fi Simple Configuration Technical Specification v2.0.5" (available for download here). Android makes use of this standard format for configuring WiFi networks, I wrongly assumed it was proprietary.
Firstly, I created an NFC helper class (aptly named NFCHelper.java) which has all the byte constants needed to construct the record. Then, I created a hacky method for creating one of the two records required. The spec is actually fairly useless here, what I did was examined a number of payloads of tags that had been successfully configured via the Android OS. Finally, you need to have a mechanism to prepend a "Handover Select Record (NFC WKT Hs)" (see page 90 of WiFi spec). I believe this record "tells" Android to register the network in the following token.
How to create the handover record:
ndefRecords = new NdefRecord[2];
byte[] version = new byte[] { (0x1 << 4) | (0x2)};
ndefRecords[0] = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_HANDOVER_REQUEST, new byte[0], version);
// and then obviously add the record you create with the method below.
Method for creating the configuration token:
private NdefRecord createWifiRecord(String[] data) {
String ssid = data[0];
String password = data[1];
String auth = data[2];
String crypt = data[3];
byte[] authByte = getAuthBytes(auth);
byte[] cryptByte = getCryptBytes(crypt);
byte[] ssidByte = ssid.getBytes();
byte[] passwordByte = password.getBytes();
byte[] ssidLength = {(byte)((int)Math.floor(ssid.length()/256)), (byte)(ssid.length()%256)};
byte[] passwordLength = {(byte)((int)Math.floor(password.length()/256)), (byte)(password.length()%256)};
byte[] cred = {0x00, 0x36};
byte[] idx = {0x00, 0x01, 0x01};
byte[] mac = {0x00, 0x06};
byte[] keypad = {0x00, 0x0B};
byte[] payload = concat(NFCHelper.CREDENTIAL, cred,
NFCHelper.NETWORK_IDX, idx,
NFCHelper.NETWORK_NAME, ssidLength, ssidByte,
NFCHelper.AUTH_TYPE, NFCHelper.AUTH_WPA_PERSONAL, authByte,
NFCHelper.CRYPT_TYPE, NFCHelper.CRYPT_WEP, NFCHelper.CRYPT_AES_TKIP,
NFCHelper.NETWORK_KEY, passwordLength, passwordByte);
// NFCHelper.MAC_ADDRESS, mac);
return NdefRecord.createMime(NFC_TOKEN_MIME_TYPE, payload);
}
License and gist here. You can find an implementation of the concat method anywhere on the net, or just write your own.
Note: this is a fairly hacky implementation (as you may notice). I am including the AES and AES/TKIP bytes as I found in testing it worked for a variety of networks using different encryption/auth methods under Android 5.*
Please feel free to change the function prototype, the String array just worked nicely with what I was doing.
Using the two records created in the first snippet above, you should then pass that into an NdefMessage and write it to your tag.
One day soon I'm going to do a write up and a far better/robust soln with graphics and stuff too, so I'll update this answer then.
The call of doStringCommand("WPS_NFC_CONFIG_TOKEN WPS " + netId) in the end is handled by the wpa_supplicant module. This feature is described here. I think the actual implementation of this can be found in wps_supplicant.c.
What you are actually trying to do isn't something Android specific actually. It's defined in the "WiFi Simple Configuration Technical Specification", which you can download by filling this form. The relevant part should be 10.1.2 Configuration Token.
NfcUtils.java has a working implementation for this! There are a few FIXMEs and TODOs, but in total it works and should give you a pretty good idea of what you need to do.
In case you want to parse such NdefRecords yourself and do something with the SSID and key, NfcWifiProtectedSetup.java shows how to do that.

Load java function in Lua

Simple QUESTION : Are there ways to run or load java functions inside Lua?
I am trying to create a phone application that transfers files between server and client using Lua. The server uses Java while client uses Lua.
this is a lua function that receives file
function UDPClientModule.receiveFile()
local data, status
local chunks = {}
while true do
data, status = udp:receive()
print("status: ", status)
if data ~= nil then
table.insert(chunks, data)
--the filename is the last chunk to be received
if string.match(data, ".jpg") then
-- but strangely returns true
break
end
end
socket.sleep(0.5)
end
--combineAndOpenImage(t)
end
No problems so far. However, the chunks sent by the server are encapsulated in a class like this:
public class FileChunk {
private List<Data> dataList;
//functions below
}
public class Data{
private byte[] fileData;
// functions and adding file headers below
} // then UDPServer.java sends bytes of FileChunk
Because of this, packets received by the lua function are strange which also results in string.match(data, ".jpg") returning true. So I want to run java files (eg. UDPClient.java) in order to receive and decipher the chunks, instead of lua.
I don't want to change the server nor migrate the client language to java. I haven't found any resources about this so I need help.
You would need to create a wrapper library, such as the ones in C. I do not know how, but I hope this provides you a sense of direction.

Start a lightweight web-server using Swift to receive OAuth1.0 callback in iOS App

I'm a newbie in Swift (and iPhone dev). I'm working on a project where I need to build an iOS (using swift) mobile client to demonstrate OAuth1.0 (3-legged flow).
I'm not finding any concrete solution to start a server using swift. I need to pass a call-back endpoint to the request_token url so that my program can receive the oauth_verifierId.
I found the following close solutions (libs) from net, but either lack of examples/docs or due to my less exp on swift, things are not in place yet.
https://github.com/swisspol/GCDWebServer - No/less concrete example (not sure how to import this in swift project)
https://github.com/robbiehanson/CocoaHTTPServer - Looks good but not
getting any e2e solution. I want to avoid Obj-C lib in my Swift project.
https://github.com/glock45/swifter
Actually, I don't need a wrapper like above. It would be best if I could write a Java equivalent like following.
ServerSocket s = new ServerSocket(7000);
Socket remote = s.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(
remote.getInputStream()));
PrintWriter out = new PrintWriter(remote.getOutputStream());
String str = null;
while (!str.equals("")){
str = in.readLine();
if(str.startsWith("GET")){
String[] splitStr = str.split("&");
for(String s1 : splitStr){
if(s1.startsWith("oauth_verifier")){
String verifierId = s1.split("=")[1];
System.out.println("VerifierId - " + verifierId);
}
}
break;
}
}
I think my answer would a little bit late, just put a sign here for later comers.
If you are about to use GCDWebServer:
pod "GCDWebServer", "~> 3.0" in your Podfile, then pod install, pod update.
Put a file named APP_NAME-Bridging-Header.h in SOME_PATH, put these lines below the #define statement:
#import "GCDWebServer.h"
#import "GCDWebServerDataResponse.h"
Go Project Name -> Build Settings -> Search for bridging -> update Objective-C Bridging Header to $(SRCROOT)/SOME_PATH/APP_NAME-Bridging-Header.h.
Now the Objective-C library is globally imported, you could use it everywhere.
Use this line of code to instantiate a GCDWebServer instance:
let webServer = GCDWebServer()
Now play it with yourself :)

Hard link count

What is a more efficient way to retrieve the hard link count of a file, that scales with high numbers of files?
I'm writing an application that scans all files on a volume to draw a graph. It is similar to a freeware program inconveniently called Scanner, which does takes Hard links into account, and scans really fast, faster than I can achieve in Java without even checking hard links.
I already tried checking the hard link count in the following (slow) ways:
(Examples are very simplified for readability)
Via the CMD program STAT (windows)
process = Runtime.getRuntime().exec(new String[]{"stat", "--printf=%h", "\"" + filePath + "\""});
in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String inpMsg = in.readLine();
linkCount = Integer.parseInt(inpMsg);
and using a JNI call to GetFileInformationByHandle:
String lpFileName = filePath;
int dwShareMode = Kernel32.FILE_SHARE_READ | Kernel32.FILE_SHARE_WRITE;
Pointer lpSecurityAttributes = null;
int dwCreationDisposition = Kernel32.OPEN_EXISTING;
int dwFlagsAndAttributes = 0;
int hTemplateFile = 0;
hFile = Kernel32.INSTANCE.CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
Memory lpFileInformation = new Memory(56);
Kernel32.INSTANCE.GetFileInformationByHandle(hFile, lpFileInformation);
linkCount = lpFileInformation.getInt(40);
To give an idea of why I want a faster method, here is a list of how fast different processes can iterate over all files on my C: drive (170000 files):
Alt+Enter on C:\: 19000 files per second (9 seconds)
Scanner (mentioned above): 7800 files per second (22 seconds)
Java (no Hard links): 1750 files per second (98 seconds)
Java (with JNI): 40 files per second (1:10 hours (projected))
Java (with STAT): 8 files per second (5:50 hours (projected))
The fact that Java is slower than Scanner might have to do with the fact that I'm using File.listFiles() instead of the new FileVisitor, but I won't accept a speed of 40 files/second which is 43 times slower than without hard links.
(I ran these tests after already scanning several times before. The first scan always takes several times longer)

Categories

Resources