I am new to KMM, but trying to port a standard android app written in Java to KMM.
So, I have the following method:
private static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DSA");
keyPairGen.initialize(2048);
KeyPair pair = keyPairGen.generateKeyPair();
return pair;
}
With the keypair, I am going to sign a byte array and send the signature together with the public key to a java server, think of it as a variant of FIDO2.
Converting to Kotlin was not the problem, but then the java.security.* classes are used, which seems wrong when having in mind that there should also be an iOS variant. So my idea was to have in commonMain a function which would receive the byte array to be signed and returns an object containing the signature and the publickey for verification, in androidMain then the actual implementation for doing this with the code above - but how to do this for iosMain ? I can't figure out how to generate a keypair for signing using pure Kotlin for ios...
Related
I cannot get the Sendgrid public key verification to work in my application. I already have all the prerequisites configured. (API key is added, Signed webhook is enabled etc)
This is my approach to test the webhook.
I register a webhook.site url as the webhook in Sendgrid
I invoke the webhook from Sendgrid so that I get the call to webook.site
I export the request received to webhook.site as a Curl.
I import it into Postman
In Postman, I change the URL to a one from a backend service that is running in my localhost and invoke the call from Postman.
Here is my code to verify the signature. This is a exact copy of what Sendgrid has provided here.
public boolean VerifySignature(ECPublicKey publicKey, byte[] payload, String signature, String timestamp)
throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException, IOException {
// prepend the payload with the timestamp
final ByteArrayOutputStream payloadWithTimestamp = new ByteArrayOutputStream();
payloadWithTimestamp.write(timestamp.getBytes());
payloadWithTimestamp.write(payload);
// create the signature object
final Signature signatureObject = Signature.getInstance("SHA256withECDSA", "BC");
signatureObject.initVerify(publicKey);
signatureObject.update(payloadWithTimestamp.toByteArray());
// decode the signature
final byte[] signatureInBytes = Base64.getDecoder().decode(signature);
// verify the signature
return signatureObject.verify(signatureInBytes);
}
Now this method always returns false when it is called from below controller method.
#PostMapping("/sendgrid-callback")
public boolean acceptSendgridCallback(
#RequestBody String rawData,
#RequestHeader("X-Twilio-Email-Event-Webhook-Timestamp") String timestamp,
#RequestHeader("X-Twilio-Email-Event-Webhook-Signature") String signature
) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException, SignatureException, IOException, InvalidKeyException {
System.out.println("Req body = \n" + rawData);
ECPublicKey ecdsaKey = eventWebhook.ConvertPublicKeyToECDSA
("public key taken from sendgrid");
boolean b = eventWebhook.VerifySignature(ecdsaKey, rawData, signature, timestamp);
return b;
}
I am unable to find the cause for that honestly.
Can someone help here.
You will need to add the \r\n with the request body to pass the verification if you are testing using unit test or your own http request. You don't need to add that if you are testing using actual sendgrid webhook request.
I need to generate a keypair in my Flutter app, There is one library called RSA which does parse a pair of public/private keys and is able to encrypt and decrypt strings using them, but it doesn't have the ability to generate a new KeyPair (preferably from a given string).
How can I generate the keys in the first place? Am I missing something?
//Future to hold our KeyPair
Future<crypto.AsymmetricKeyPair> futureKeyPair;
//to store the KeyPair once we get data from our future
crypto.AsymmetricKeyPair keyPair;
Future<crypto.AsymmetricKeyPair<crypto.PublicKey, crypto.PrivateKey>> getKeyPair()
{
var helper = RsaKeyHelper();
return helper.computeRSAKeyPair(helper.getSecureRandom());
}
It's easy using the fast_rsa package:
import 'package:fast_rsa/fast_rsa.dart';
KeyPair keyPair1 = await RSA.generate(2048);
print(keyPair1.privateKey);
print(keyPair1.publicKey);
https://pub.dev/packages/fast_rsa
My server provides a Self Signed certificate when calling its HTTPS API. I have the certificate file in the asset folder and referenced its path in pubspec.yaml
I have tried passing the certificate to SecurityContext and then using that context to create an HttpClient. But the way I'm passing the certificate to SecurityContext is not working. Here is the code:
Future<ByteData> getFileData(String path) async {
return await rootBundle.load(path);
}
void initializeHttpClient() async {
try {
Future<ByteData> data = getFileData('assets/raw/certificate.crt');
await data.then((value) {
var context = SecurityContext.defaultContext;
context.useCertificateChainBytes(value.buffer.asInt8List());
client = HttpClient(context: context);
});
} on Exception catch (exception) {
print(exception.toString());
}
}
The SecurityContext has two methods:
1) useCertificateChain() this accepts a file path. But when I give the path of the file in my asset folder ('assets/raw/certificate.crt'). It says file not found.
2) useCertificateChainBytes() the above code is using this method. But this also gives me error like (unexpected end of file).
Solution as of now
I am bypassing it using client.badCertificateCallback = (X509Certificate cert, String host, int port)=> true;.
but I'd like to make it work with certificate
It's not clear from your question what the role of the self-signed certificate is. Based on your work around, I assume that it's a server side certificate that you have installed in the HTTPS server. (It's not a client side certificate that you would like to pass to the server.)
So, what you need to do is to get the Dart HttpClient to trust that certificate, which will be passed to it by the server as part of the TLS handshake. (By setting the callback you have made the client trust any certificate, not just your server's.)
To set the trusted certificate use setTrustedCertificatesBytes in place of useCertificateChainBytes (which you would use if your certificate was a client side one).
You cannot access assets directly as Files as they are bundled by the build. You are doing the right thing by loading them and using the ...Bytes methods. You could improve the readability of your code like this (removing the then). Also, note the subtle change to Uint8List
ByteData data = await rootBundle.load('assets/raw/certificate.crt');
SecurityContext context = SecurityContext.defaultContext;
context.setTrustedCertificatesBytes(data.buffer.asUint8List());
client = HttpClient(context: context);
I know Groovy DSL is able to generate a random value.
I have used stub runner server so that I can hit the stubs from the server and get response. however when I refresh the browser I get the same response again. The Groovy DSL is just generating a static stub, and is always returning the same response as I requested.
How can I get a random response without re-generate the stubs in this case?
Also a similar question was asked by someone a year ago, it was written in the answer that it is not possible. Is it still not possible or there is a way now to do it?
You would have to create your own WireMock extension. Check this section of the docs: https://docs.spring.io/spring-cloud-contract/docs/current/reference/html/advanced.html#customization-wiremock
95.5.6 Registering Your Own WireMock Extension WireMock lets you register custom extensions. By default, Spring Cloud Contract
registers the transformer, which lets you reference a request from a
response. If you want to provide your own extensions, you can register
an implementation of the
org.springframework.cloud.contract.verifier.dsl.wiremock.WireMockExtensions
interface. Since we use the spring.factories extension approach, you
can create an entry in META-INF/spring.factories file similar to the
following:
org.springframework.cloud.contract.verifier.dsl.wiremock.WireMockExtensions=\
org.springframework.cloud.contract.stubrunner.provider.wiremock.TestWireMockExtensions
org.springframework.cloud.contract.spec.ContractConverter=\
org.springframework.cloud.contract.stubrunner.TestCustomYamlContractConverter
The following is an example of a custom extension:
TestWireMockExtensions.groovy.
package org.springframework.cloud.contracthttps://docs.spring.io/spring-cloud-contract/docs/current/reference/html/advanced.html#customization-wiremock.verifier.dsl.wiremock
import com.github.tomakehurst.wiremock.extension.Extension
/** * Extension that registers the default transformer and the custom one */ class TestWireMockExtensions implements WireMockExtensions { #Override List<Extension> extensions() { return [
new DefaultResponseTransformer(),
new CustomExtension() ] } }
class CustomExtension implements Extension {
#Override String getName() { return "foo-transformer" } }
You would have to create an extension that modifies the response and generates a piece of it. That extension needs to be available both on the consumer and the producer sides.
I want to perform SHA256 hashing in a Blackberry application. Searching, I found the Bouncy Castle project has a crypto library for this, but I can't find any samples to show how to use SHA256 hashing.
Just reposting user598312's answer as a response instead of a comment, so people know the solution.
private static byte[] getSHA512(String key) {
SHA512Digest digester = new SHA512Digest();
byte[] retValue = new byte[digester.getDigestSize()];
digester.update(key.getBytes(), 0, key.length());
digester.doFinal(retValue, 0);
return retValue;
}
BlackBerry has built-in implementations of nearly everything in the BouncyCastle API. For SHA256, there is SHA256Digest.