I try to parse certificate data from an big .csv file. The documentation says it is a X509 certificate stored in raw data encoded with base64.
So i tried to decode it and load the data with java using this code:
protected X509Certificate parseCert(byte [] bytes) {
if (bytes != null) {
InputStream in = new ByteArrayInputStream(org.apache.commons.net.util.Base64.decodeBase64(bytes));
X509Certificate certificate = null;
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
certificate = (X509Certificate) cf.generateCertificate(in);
} catch (Exception ex) {
ex.printStackTrace();
}
return certificate;
}
System.out.println("Null value in bytes!");
return null;
}
I always get a CertificateException saying "Empty Data". I don't know what i am doing wrong!
With a CSV reader the data looks good, or must I cut off \x3 ?
\x308202e23082024ba0......
\x30820224308201....
And:
\x308201db30820144a00302010202020462300d06092a864886f70d010104050030323130302e0603550403132750616e646f436c69656e74363930413639343632353536363738423737414435353341314332393020170d3133303330383137313230315a180f33303132303232393137313230315a30323130302e0603550403132750616e646f436c69656e743639304136393436323535363637384237374144353533413143323930819f300d06092a864886f70d010101050003818d0030818902818100ad97e2fd61997ca4898383b957de7d44fcf9cf4199c915538fadfd644d36df3ea1eea1d69a6b8ad75a313cb25b479966ed7f831638bbea4ac0f2f2d1452b81ed0ff73da55f477e81f4cd4dad7ca26f29a7eb38d097ec90446e531bac72e29882f1df06a75893f7d6e115d11200bff5a813ea050591f2fcc50ab2d13ddc7d3fdd0203010001300d06092a864886f70d010104050003818100603e9d0ad64f80363e3cae94b28dcb9a25409a59ce7876bd24990b62ef3901788e2c0b3a0be22f4c07deb7c005d82f46a105a6abbfca4505403a7c2248be296aae5367e04fc22b0a93f6272263a3ebf25279e5c1ae415fd9e14898c11dc74c18c128e35e7d8467028689cc304fc95359c1f7eb89018ca750145ea81f498880af
May be someone can help?
The certificate is not base64-encoded but hex-encoded.
Changing the code of the OP's parseCert method to
protected X509Certificate parseCert(byte[] bytes)
{
if (bytes != null)
{
InputStream in = new ByteArrayInputStream(Hex.decode(bytes));
X509Certificate certificate = null;
try
{
CertificateFactory cf = CertificateFactory.getInstance("X.509");
certificate = (X509Certificate) cf.generateCertificate(in);
}
catch (Exception ex)
{
ex.printStackTrace();
}
return certificate;
}
System.out.println("Null value in bytes!");
return null;
}
(making use of the BouncyCastle hex decoder org.bouncycastle.util.encoders.Hex, but any other should also do) results in successful parsing of the certificate in
#Test
public void test24542431() throws CertificateEncodingException, IOException
{
String hexEncodedCert = "308201db30820144a00302010202020462300d06092a864886f70d010104050030323130302e0603550403132750616e646f436c69656e74363930413639343632353536363738423737414435353341314332393020170d3133303330383137313230315a180f33303132303232393137313230315a30323130302e0603550403132750616e646f436c69656e743639304136393436323535363637384237374144353533413143323930819f300d06092a864886f70d010101050003818d0030818902818100ad97e2fd61997ca4898383b957de7d44fcf9cf4199c915538fadfd644d36df3ea1eea1d69a6b8ad75a313cb25b479966ed7f831638bbea4ac0f2f2d1452b81ed0ff73da55f477e81f4cd4dad7ca26f29a7eb38d097ec90446e531bac72e29882f1df06a75893f7d6e115d11200bff5a813ea050591f2fcc50ab2d13ddc7d3fdd0203010001300d06092a864886f70d010104050003818100603e9d0ad64f80363e3cae94b28dcb9a25409a59ce7876bd24990b62ef3901788e2c0b3a0be22f4c07deb7c005d82f46a105a6abbfca4505403a7c2248be296aae5367e04fc22b0a93f6272263a3ebf25279e5c1ae415fd9e14898c11dc74c18c128e35e7d8467028689cc304fc95359c1f7eb89018ca750145ea81f498880af";
X509Certificate cert = parseCert(hexEncodedCert.getBytes());
Files.write(FileSystems.getDefault().getPath("target/test-outputs", "24542431.crt"), cert.getEncoded());
}
which is not trusted here, though:
Related
I am currently creating a webpage that displays a table with data from an Mysql DB. One of the columns is a file (stored as a BLOB in the DB). The name of the file is an anchor tag that links to my download.java servlet. My download servlet works when deploying locally, however now that I have deployed to an AWS ElasticBeanstalk instance the servlet does not work.
In the log it says the following:
org.apache.coyote.http11.AbstractHttp11Processor.process Error parsing HTTP request header
Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.
java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
and
/usr/share/tomcat8/Downloads/sdc.png (No such file or directory)
The servlet code:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "dbURL?serverTimezone=" + TimeZone.getDefault().getID();
Connection conn = DriverManager.getConnection(url , "username" , "password");
String fn = request.getParameter("Id");
String selectSQL = "SELECT file FROM Requests WHERE fileID=?";
PreparedStatement pstmt = conn.prepareStatement(selectSQL);
pstmt.setString(1, fn);
ResultSet rs = pstmt.executeQuery();
// write binary stream into file
String home = System.getProperty("user.home");
File file = new File(home+"/Downloads/" + fn);
FileOutputStream output = new FileOutputStream(file);
System.out.println("Writing to file " + file.getAbsolutePath());
while (rs.next()) {
InputStream input = rs.getBinaryStream("file");
byte[] buffer = new byte[1024];
while (input.read(buffer) > 0) {
output.write(buffer);
}
}
RequestDispatcher rd = request.getRequestDispatcher("/requests.jsp");
rd.forward(request, response);
rs.close();
pstmt.close();
} catch (SQLException | IOException e) {
System.out.println(e.getMessage());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
The servlet should download the file from the Mysql DB to the users download folder. However, this only works locally, on the AWS server it fails. I assume this is because:
String home = System.getProperty("user.home");
returns the home path of the AWS server instance, rather than the path of the users/visitors home path.
Please help me adjust my servlet so that it works on the AWS server
UPDATE: After some research I think that getting the path to the client's download folder is not possible. Now I think I need to make us of a 'save as' dialog box. Any tips on how to do this and resources that could help me do this is appreciated
I was able to get my servlet working using code posted in a question here
My working code now looks like this:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Connection conn = null;
try {
// Get Database Connection.
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "dbURL?serverTimezone=" + TimeZone.getDefault().getID();
conn = DriverManager.getConnection(url , "username" , "password");
String fileName = request.getParameter("Id");
System.out.println("File Name: " + fileName);
// queries the database
String sql = "SELECT file FROM requests WHERE fileID= ?";
PreparedStatement statement = conn.prepareStatement(sql);
statement.setString(1, file);
ResultSet result = statement.executeQuery();
if (result.next()) {
// gets file name and file blob data
Blob blob = result.getBlob("file");
InputStream inputStream = blob.getBinaryStream();
int fileLength = inputStream.available();
System.out.println("fileLength = " + fileLength);
ServletContext context = getServletContext();
// sets MIME type for the file download
String mimeType = context.getMimeType(fileID);
if (mimeType == null) {
mimeType = "application/octet-stream";
}
// set content properties and header attributes for the response
response.setContentType(mimeType);
response.setContentLength(fileLength);
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"", fileID);
response.setHeader(headerKey, headerValue);
// writes the file to the client
OutputStream outStream = response.getOutputStream();
byte[] buffer = new byte[1024];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
inputStream.close();
outStream.close();
}
else {
// no file found
response.getWriter().print("File not found for the fn: " + fileName);
}
} catch (Exception e) {
throw new ServletException(e);
}
}
I need to make mutiple rest api calls for fetching instance, volume and vnic details. Can i reuse the same signer object created for signing the other calls?
Signer object method
public RequestSigner getSigner(Properties properties, String pemFilePath, String apiKey) {
InputStream privateKeyStream;
PrivateKey privateKey = null;
try {
privateKeyStream = Files.newInputStream(Paths.get(pemFilePath));
privateKey = PEM.readPrivateKey(privateKeyStream);
} catch (InvalidKeySpecException e) {
// throw new RuntimeException("Invalid format for private key");
properties.setProperty(OracleCloudConstants.CUSTOM_DC_ERROR,
FormatUtil.getString("am.webclient.oraclecloud.customdc.invalidformat"));
AMLog.debug("OracleCloudDataCollector::CheckAuthentication()::Invalid format for private key::"
+ e.getMessage());
e.printStackTrace();
} catch (IOException e) {
properties.setProperty(OracleCloudConstants.CUSTOM_DC_ERROR,
FormatUtil.getString("am.webclient.oraclecloud.customdc.failedload"));
AMLog.debug(
"OracleCloudDataCollector::CheckAuthentication()::Failed to load private key::" + e.getMessage()); //No I18N
e.printStackTrace();
// throw new RuntimeException("Failed to load private key");
}
RequestSigner signer = null;
if (privateKey != null) {
signer = new RequestSigner(apiKey, privateKey);
}
return signer;
}
One signer object may be used to sign multiple requests. In fact, the SDK implementation does this too.
It is not clear what version of the SDK you are using. In version 1.5.7 (the most recent at the time of writing), com.oracle.bmc.http.signing.RequestSigner (https://github.com/oracle/oci-java-sdk/blob/master/bmc-common/src/main/java/com/oracle/bmc/http/signing/RequestSigner.java#L16) is an interface which cannot be new’ed as per the snippet above.
i'm using java and i want to consume the json in this url : http://jiraserver/rest/dev-status/latest/issue/detail?issueId=13879&applicationType=stash&dataType=repository
on the browser this url works perfectly and i get all json data needed but in my java program i get
java.io.IOException: Server returned HTTP response code: 400 for URL:
http://jiraserver/rest/dev-status/latest/issue/detail?issueId=13879&applicationType=stash&dataType=repository
public static void main(String[] args) {
System.out
.println(jsonGetRequest("http://jiraserver/rest/dev-status/latest/issue/detail?issueId=13879&applicationType=stash&dataType=repository
"));
}
private static String streamToString(InputStream inputStream) {
String text = new Scanner(inputStream, "UTF-8").useDelimiter("\\Z").next();
return text;
}
public static String jsonGetRequest(String urlQueryString) {
String json = null;
try {
URL url = new URL(urlQueryString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("charset", "utf-8");
connection.connect();
InputStream inStream = connection.getInputStream();
json = streamToString(inStream); // input stream to string
} catch (IOException ex) {
ex.printStackTrace();
}
return json;
}
am i missing something ? if there's any simple implementation to consume that url feel free
My System: A Security Provider generates JWT Tokens based on a Private Key. The Private Key belongs to a Certificate which will expire.
Is it possible to set multiple Public Keys in Resource Server?
I would like to do a rolling Update, so for a short time it has to Support the old Public Key and a new Public Key. Thats a default use case because the certificates expires.?
Can oauth/token_key deliver multiple Keys or just one?
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
Resource resource = new ClassPathResource("public.txt");
String publicKey = null;
try {
publicKey = IOUtils.toString(resource.getInputStream());
}
catch (final IOException e) { throw new RuntimeException(e);
}
**converter.setVerifierKey(publicKey);**
**converter.setVerifierKeys(publicKey1, publicKey2);?**
return converter;
}
http://www.baeldung.com/spring-security-oauth-jwt
Thanks
This is not standard practice and Spring's jwt framework does not support multiple security providers (or multiple active verifier keys) out-of-the-box. Having said that, what you wish to do is theoretically possible. You would have wire-up a new implementation for the AccessTokenConverter similar to the JwtAccessTokenConverter, but implement the decode method like this:
protected Map<String, Object> decode(String token) {
try {
Jwt jwt = JwtHelper.decodeAndVerify(token, verifier1);
String content = jwt.getClaims();
Map<String, Object> map = objectMapper.parseMap(content);
if (map.containsKey(EXP) && map.get(EXP) instanceof Integer) {
Integer intValue = (Integer) map.get(EXP);
map.put(EXP, new Long(intValue));
}
return map;
}
catch (Exception e) {
//try the other verifier
try {
Jwt jwt = JwtHelper.decodeAndVerify(token, verifier2);
String content = jwt.getClaims();
Map<String, Object> map = objectMapper.parseMap(content);
if (map.containsKey(EXP) && map.get(EXP) instanceof Integer) {
Integer intValue = (Integer) map.get(EXP);
map.put(EXP, new Long(intValue));
}
return map;
}
catch(InvalidTokenException te){
throw te;
}catch (Exception e) {
throw new InvalidTokenException("Cannot convert access token to JSON", e);
}
}
}
Essentially, the code above trys to verify the first key but if any exception is thrown it will try to validate the second one.
I would also suggest you override to tokenConverter to split the provided token by some delimiter like a "." or something that is not in the encoding char set of your hash algo that generates the verifier key. Then when calling the you could do: setVerifierKey("verifierKey1" + delimiter + "verifierKey2")
Note: I have not tested this code, just some thoughts :)
I am using an api that returns an error 400 if URL is invalid and error 401 if daily qouta is exhausted by 50%. it also returns the json but am not able to download this json as an exception occurs if these error occurs. the api am using is
http://www.sharedcount.com/documentation.php
the code am using write now is...
private void _download_serialized_json_data(Uri Url)
{
var webClient = new WebClient();
var json_data = string.Empty;
// attempt to download JSON data as a string
try
{
webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
webClient.DownloadStringAsync(Url);
}
catch (Exception) { }
}
void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
String Json = null;
try
{
Json = e.Result;
}
catch (Exception ex)
{
}
if(Json!=null)
{
data=JsonConvert.DeserializeObject<RootObject>(Json);
result.Text = "facebook : "+data.Facebook.like_count+"\nGooglePlus : "+data.GooglePlusOne;
}
else
{
result.Text = "Invald URL \nor you exceeded your daily quota of 100,000 queries by 50%.";
}
}
currently am showing both errors if exception occurs. but i want to download the json and display that. how should i do that
To get the response content, you will need to use System.Net.Http.HttpClient instead. Install it from here: Microsoft HTTP Client Libraries
Then try this:
private async void Foo2()
{
Uri uri = new Uri("http://localhost/fooooo");
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.GetAsync(uri);
HttpStatusCode statusCode = response.StatusCode; // E.g.: 404
string reason = response.ReasonPhrase; // E.g.: Not Found
string jsonString = await response.Content.ReadAsStringAsync(); // The response content.
}
You can try something like this,
void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
String Json = null;
if(e.Error != null)
{
//Some error occured, show the error message
var ErrorMsg = e.Error.Message;
}
else
{
//Got some response .. rest of your code
Json = e.Result;
}
}
I ran into this same issue using WebClient, I saw the error response stream being captured in Fiddler, but my .NET code was catching the exception and did not appear to be capturing the response stream.
You can read the Response stream from the WebException object to get the response data stream out.
using (System.Net.WebClient client = new System.Net.WebClient())
{
string response = "";
try
{
response = client.UploadString(someURL, "user=billy&pass=12345");
}
catch(WebException ex)
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(ex.Response.GetResponseStream()))
{
string exResponse = sr.ReadToEnd();
Console.WriteLine(exResponse);
}
}
}