I am trying to retrieve the certificate of an Microsoft Exchange contact. It was set in Outlook by importing it in the certificate tab.
It is available by using PidTagUserX509Certificate on EWS, see https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxoabk/e4de26c4-9bcb-4da2-99c6-5f67aebc221a
but i have to admit i do not understand how to handle the object as described in the documentation.
I try to base64-decode the retrieved data, then use a X509 CertificateFactory to read the certificate.
byte[] bytes = Base64.decode(certificateValue, Base64.DEFAULT);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(is);
This leads to an parsing exception: error:0c0000be:ASN.1 encoding routines:OPENSSL_internal:WRONG_TAG
My Code runs on Android, but the issue should be universal.
You can find the base64 data here: https://pastebin.com/dCnMtjn4
Any idea how i could get to the certificate?
It seems that the data is enveloped. First 12 bytes is kind of envelope (idk what it is) and the rest bytes look as X.509 cert. After first line, skip first 12 bytes and pass the rest of the byte array to ByteArrayInputStream. I'm not familiar with Java, but there should be kind of .Skip method for arrays? Quick google suggest, you can do it this way:
byte[] bytes = Base64.decode(certificateValue, Base64.DEFAULT);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
is.skip(12);
X509Certificate certificate = (X509Certificate)certificateFactory.generateCertificate(is);
Related
I have a Nuxt application that needs to retrieve some information from a Spring Boot-based auth service.
Right now I sign a text message on the Nuxt app (the auth server is aware of that text message), using node-forge, and then I send it encrypted and with the signature for verification on the auth service.
The problem is that the auth service keeps telling me that the size of the signature is wrong, with a java.security.SignatureException: Signature length not correct: got 3XX but was expecting 256.
Here is the code generating the encrypted message and signature on the Nuxt side:
var md = forge.md.sha256.create();
md.update("123"); // for example purposes
var sign = pPrivateKey.sign(md);
var digestBytes = md.digest().bytes();
console.log("Signature:", sign );
console.log("Encrypted:", digestBytes);
console.log("Encrypted B64:", Buffer.from(digestBytes).toString("base64"));
var keyAuthB64Url = Buffer.from(digestBytes).toString("base64url");
var signB64Url = Buffer.from(sign).toString("base64url");
var jwt = await axios.get(process.env.URL + "/auth", { params: { encrypted: keyAuthB64Url, signature: signB64Url } });
On the auth service I have the following code:
byte[] messageBytes = Base64.getUrlDecoder().decode(encryptedMessage);
byte[] signatureBytes = Base64.getUrlDecoder().decode(signature);
Signature sign = Signature.getInstance("SHA256withRSA");
sign.initVerify(certPublicKey);
sign.update(messageBytes);
boolean verified = sign.verify(signatureBytes);
if (!verified) {
throw new Exception("Not verified!");
}
From all the debugging I have done, it seems like the Spring Boot app has a problem with the signature generated by node-forge on the Nuxt side, with a signature generated in the Spring Boot app the verification works.
There are several issues:
First, the bug that was already mentioned in the comment: While the NodeJS code does not hash implicitly, the Java side does. Therefore, hashing must not be done explicitly on the Java side:
byte[] messageBytes = "123".getBytes("utf-8");
...
sign.update(messageBytes); // Fix 1: Don't hash
Also, in the NodeJS code, sign() returns the data as a bytes string, which must therefore be imported into a NodeJS buffer as a 'binary':
var keyAuthB64Url = Buffer.from(digestBytes, "binary").toString("base64url"); // Fix 2: Import via 'binary' encoding
Without explicit specification of the encoding, a UTF-8 encoding is performed by default, which irreversibly corrupts the data.
And third, latin1 is implicitly used as encoding when generating the hash in the NodeJS code. Other encodings must be specified explicitly, e.g. for the common UTF-8 with utf8:
md.update("123", "utf8"); // Fix 3: Specify the encoding
For the example data 123 used here, this fix has no effect, which changes as soon as characters with a Unicode value larger than 0x7f are included, e.g. 123ยง. Note that there is little margin for error in the specification of the encoding, e.g. utf-8 would be ignored (because of the hyphen) and latin1 would be used silently.
With these fixes, verification with the Java code works.
In a spring boot application I read an image file from a remote service, which returns byte array and in headers I can check what is file extension:
ResponseEntity<byte[]> result = restTemplate.exchange(url, HttpMethod.GET, entity, byte[].class);
Now I want to put this byte array in a S3 bucket in a folder which I decide during run time, for example folder name can base don current timestamp.
I checked AmazonS3 class, but it doesnt seem to have any such API which can help me?
How can this be done?
As per example from documentation:
https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/examples-s3-objects.html#upload-object
// Put Object. here 'bytes' is byte array.
PutObjectResponse response = s3.putObject(PutObjectRequest.builder().bucket(bucketName).key(filePathLocation).build(),RequestBody.fromBytes(bytes));
You can use the MinIO java S3 client. Here you can find the documentation.
The code will look something like the following one:
MinioClient minioClient =
MinioClient.builder()
.endpoint("https://play.min.io")
.credentials("Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG")
.build();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 1000; i++) {
builder.append(
"Sphinx of black quartz, judge my vow: Used by Adobe InDesign to display font samples. ");
builder.append("(29 letters)\n");
builder.append(
"Jackdaws love my big sphinx of quartz: Similarly, used by Windows XP for some fonts. ");
builder.append("(31 letters)\n");
builder.append(
"Pack my box with five dozen liquor jugs: According to Wikipedia, this one is used on ");
builder.append("NASAs Space Shuttle. (32 letters)\n");
builder.append(
"The quick onyx goblin jumps over the lazy dwarf: Flavor text from an Unhinged Magic Card. ");
builder.append("(39 letters)\n");
builder.append(
"How razorback-jumping frogs can level six piqued gymnasts!: Not going to win any brevity ");
builder.append("awards at 49 letters long, but old-time Mac users may recognize it.\n");
builder.append(
"Cozy lummox gives smart squid who asks for job pen: A 41-letter tester sentence for Mac ");
builder.append("computers after System 7.\n");
builder.append(
"A few others we like: Amazingly few discotheques provide jukeboxes; Now fax quiz Jack! my ");
builder.append("brave ghost pled; Watch Jeopardy!, Alex Trebeks fun TV quiz game.\n");
builder.append("---\n");
// Create a InputStream for object upload.
ByteArrayInputStream bais = new ByteArrayInputStream(builder.toString().getBytes("UTF-8"));
// Create object 'my-objectname' in 'my-bucketname' with content from the input stream.
minioClient.putObject(
PutObjectArgs.builder().bucket("my-bucketname").object("my-objectname").stream(
bais, bais.available(), -1)
.build());
bais.close();
System.out.println("my-objectname is uploaded successfully");
The full code can be found here.
Checkout the AWS JAVA SDK:
Here the getting started section:
https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/getting-started.html
In order to use in Spring context use the Maven dependency:
https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/setup-project-maven.html
Uploading an object to S3 Bucket:
https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/examples-s3-objects.html#upload-object
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
System.out.format("Uploading %s to S3 bucket %s...\n", file_path, bucket_name);
final AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
try {
s3.putObject(bucket_name, key_name, new File(file_path));
} catch (AmazonServiceException e) {
System.err.println(e.getErrorMessage());
System.exit(1);
If I understand GCM mode correctly, it is supposed to provide not only encryption, but also authentication of the ciphertext. However when I use Ruby's OpenSSL implementation to encrypt data with AES-256-GCM mode, it will happily decrypt the data even if I tamper with the auth_tag. Am I missing something here or is the implementation indeed broken?
require 'openssl'
# ALICE encrypts some secret data
data = 'secret'
cipher = OpenSSL::Cipher.new('aes-128-gcm')
cipher.encrypt
key = cipher.random_key
iv = cipher.random_iv
cipher.auth_data = 'auth_data'
ciphertext = cipher.update(data) + cipher.final
auth_tag = cipher.auth_tag
# EVE tampers with the auth tag, e.g. dropping the last 10 bytes
auth_tag = auth_tag[0..-11]
# BOB decrypts the ciphertext
cipher = OpenSSL::Cipher.new('aes-128-gcm')
cipher.decrypt
cipher.key = key
cipher.iv = iv
cipher.auth_tag = auth_tag
cipher.auth_data = 'auth_data'
data = cipher.update(ciphertext) + cipher.final
# BOB is very sad because no error is raised!
I am using OS X built in OpenSSL version:
% openssl version
OpenSSL 0.9.8zg 14 July 2015
GCM supports multiple sizes for the authentication tag. The authentication tag is shortened in these versions by removing bytes from the right. That's exactly what your attacker seems to be doing.
Now the API is dangerously unstable. First of all, (16 - 10) * 8 = 48, which is not a valid size for AES-GCM (according to NIST SP 800-38D. Furthermore, the authentication tag size should be an input or configuration parameter of the cipher. At the very least the API should warn users to check the authentication tag size themselves instead of allowing just any authentication tag input.
So yes, you are missing something and yes, I would say the implementation - or at the very least the documentation - is broken; good catch.
I'm trying to install an applet into a J3A040 JCOP card.
As install method I have the following:
protected MainApplet() {
try {
// CREATE RSA KEYS AND PAIR
m_keyPair = new KeyPair(KeyPair.ALG_RSA_CRT, KeyBuilder.LENGTH_RSA_2048);
// STARTS ON-CARD KEY GENERATION PROCESS
m_keyPair.genKeyPair();
// OBTAIN KEY REFERENCES
m_publicKey = (RSAPublicKey) m_keyPair.getPublic();
m_privateKey = (RSAPrivateKey) m_keyPair.getPrivate();
} catch (CryptoException c) {
//this line will give you the reason of problem
short reason = c.getReason();
ISOException.throwIt(reason); // for check
}
register();
}
The installation always fails with the following error:
pro.javacard.gp.GPException: Install for Install and make selectable failed SW: 6A80
at pro.javacard.gp.GlobalPlatform.check(GlobalPlatform.java:1092)
at pro.javacard.gp.GlobalPlatform.installAndMakeSelectable(GlobalPlatform.java:798)
at pro.javacard.gp.GPTool.main(GPTool.java:478)
However, if I remove the keypair generation, everything works fine.
I have read the card specifications and it stands:
. RSA and RSA CRT (1280 up to 2048 bits keys) for en-/decryption and
signature generation and verification1 d. RSA CRT key generation (1280
up to 2048 bits keys) in a secured environment
I guess it shouldn't be a problem.
Any guesses?
The problem is caused by an invalid cast: you asked for an RSA KeyPair with the private key in the Chinese Reminder Theorem format (ALG_RSA_CRT).
That is why the getPrivate() method does not return an RsaPrivateKey instance, but an RsaPrivateCrtKey instance. Casting to RsaPrivateKey causes the 6A80 status word.
So you should either use the standard algorithm:
m_keyPair = new KeyPair(KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_2048);
, or use a correct cast:
m_publicKey = (RSAPublicKey) m_keyPair.getPublic();
m_privateKey = (RSAPrivateCrtKey) m_keyPair.getPrivate();
Is there any example on how to do constrained delegation with Java 8/7. I tried searching around with no luck
Best Regards
Here is the Java 8 code snippet that allows to generate a SPNEGO token with TGS ticket for an impersonated user:
GSSManager manager = GSSManager.getInstance();
GSSName userName = manager.createName("targetUser", GSSName.NT_USER_NAME);
GSSCredential impersonatedUserCreds =
((ExtendedGSSCredential)serviceCredentials).impersonate(userName);
final Oid KRB5_PRINCIPAL_OID = new Oid("1.2.840.113554.1.2.2.1");
GSSName servicePrincipal =
manager.createName("HTTP/webservice-host.domain.ltd", KRB5_PRINCIPAL_OID);
ExtendedGSSContext extendedContext =
(ExtendedGSSContext) manager.createContext(servicePrincipal,
new Oid("1.3.6.1.5.5.2"),
impersonatedUserCreds,
GSSContext.DEFAULT_LIFETIME);
final byte[] token = extendedContext.initSecContext(new byte[0], 0, 0);
Beware extendedContext is not established yet. Multiple rounds with server may be required.
A simple demonstration code is available at https://github.com/ymartin59/java-kerberos-sfudemo
You may also refer to the follow project code: https://github.com/tellisnz/collared-kerberos