Obtaining public key from SubjectPublicKeyInfo - java-me

I'm trying to get the public key from a SubjectPublicKeyInfo.However when I try:
PublicKey publicKey = k.generatePublic(keypsec);
byte[] encoded=publicKey.getEncoded();
SubjectPublicKeyInfo subPkInfo2 = new SubjectPublicKeyInfo(rsaEncryption, encoded);
RSAPublicKeyStructure pubKey = new RSAPublicKeyStructure((ASN1Sequence)subPkInfo2.getPublicKey());
It throws this
java.lang.IllegalArgumentException: illegal object in getInstance: org.bouncycastle.asn1.DERSequence
at org.bouncycastle.asn1.DERInteger.getInstance(DERInteger.java:37)
at org.bouncycastle.asn1.x509.RSAPublicKeyStructure.<init>(RSAPublicKeyStructure.java:63)
Any ideas? I've tried PubliKeyFactory but it simply calls the last line.

Well I shall answer my own question:
byte[] encoded=publicKey.getEncoded();
SubjectPublicKeyInfo subPkInfo2 = new SubjectPublicKeyInfo(rsaEncryption, encoded);
This is wrong. PublicKey is already an ASN1typeSubjectpublicKeyInfo. In order to create a SubjectPublicKeyInfo with this function
SubjectPublicKeyInfo(AlgorithmIdentifier algId, byte[] publicKey)
you need an Algortihm identifier and THE KEY ITSELF in encoded form. publicKey.getEncoded() is an encoded KEY + THE ALGORITHM IDENTIFIER.
Anyway. If you want to tranfosrm a SATSA public key to a Subject Public Key Info you do this:
byte[] publickeyb=SATSApublickey.getEncoded();
SubjectPublicKeyInfo subPkInfo = new SubjectPublicKeyInfo((ASN1Sequence)ASN1Object.fromByteArray(publickeyb));
And if you want to get your public key as RSAkeyparameters from the SubjectPublicKeyInfo
RSAKeyParameters param=(RSAKeyParameters) PublicKeyFactory.createKey(subPkInfo);

Related

How does Hyperledger fabric EVM generate the address from the public key?

In Ethereum, the wallet address is the last 20 bytes of the keccak256 hash of the public key of the wallet.
I am working with Hyperledger Fabric EVM, and I would like to know which is the mechanism that is used to generate the address from the public key.
I applied keccak256, sha256, and sha-3 256 to my public key, but I didn't get the correct address...
It is my private key in pem format:
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgjUp+AWrFlIVp13Dl
rpm/Uu2M++ZhOC4AbmjWdsofP7ihRANCAARWnvMdt+149KEt9yPKoLHG98lL5wPe
cGVMBMxsJhz3JLBSQlBCfLMz8fe5vIng4N7TGYt66P2HNeG/fLjwt7jI
-----END PRIVATE KEY-----
It is my public key in pem format:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVp7zHbftePShLfcjyqCxxvfJS+cD
3nBlTATMbCYc9ySwUkJQQnyzM/H3ubyJ4ODe0xmLeuj9hzXhv3y48Le4yA==
-----END PUBLIC KEY-----
It is my public key in hex format:
Public_key = 0x04569ef31db7ed78f4a12df723caa0b1c6f7c94be703de70654c04cc6c261cf724b0524250427cb333f1f7b9bc89e0e0ded3198b7ae8fd8735e1bf7cb8f0b7b8c8
And it is my address:
13065B11B498911F2A19815035D0AC24457D1BB6
I am using secp256r1
The address is the last 20 bytes of the sha3-256 of 3059301306072a8648ce3d020106082a8648ce3d030107034200 + public_key_hex
In my example, take the last 160 bits (20 bytes) of "result" :
var Public_key = 0x04569ef31db7ed78f4a12df723caa0b1c6f7c94be703de70654c04cc6c261cf724b0524250427cb333f1f7b9bc89e0e0ded3198b7ae8fd8735e1bf7cb8f0b7b8c8
var result = SHA3_256(0x3059301306072a8648ce3d020106082a8648ce3d030107034200 + Public_key)
var address = last_20bytes(result)
console.log("address = ",address);
//address = 13065B11B498911F2A19815035D0AC24457D1BB6

Verify offline an Azure AD generated JWT

I'm getting an error when verifying an Azure AD generated token. This is the current setup:
I have a token which can be pasted on https://jwt.io, and I can see in the right panel the correct claims. I assume the token is correctly formatted. I can also see in the headers that kid = piVlloQDSMKxh1m2ygqGSVdgFpA and alg: RS256. I set correctly the algo type to RS256 for verification.
I went to https://login.microsoftonline.com/common/discovery/keys to find the public key, and found the same kid = piVlloQDSMKxh1m2ygqGSVdgFpA. So I copied the corresponds public key (the string in the x5c field) and wrapped it into the correct strings to make it PKCS#8. compatible:
-----BEGIN CERTIFICATE-----
MIIDBTCCAe2gAwIBAgIQMCJcgWf4l5xPpeoEwB7DKDANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTE5MTExNTAwMDAwMFoXDTI0MTExNDAwMDAwMFowLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANF4YcKZhKTfowwWqZ84RW7bxFNgaSy3Gi85V5uJpU9jMCmZV0VFGptryNFEQ1GESmmuDutgQlkkhjr9ixkOrTA+aFPg6pLn+OG6NYS7nyKgAC1MprLH0bq06y3dH6lQPWQhd3wPP+8UIua9+9JuIfhu9Xs/HhN5cYlT5cEniV0aWuUMxgPAKcG1xolfupYhlOHjFwVN/QOaxcuk3YqGguD+sZ7PiHcJSzFnTkdvD+DtMoW1U6nDf5FuDeAEKJ7JQf7RjiRoViYxZHKrEPHG4iZ+kOhV6DQA16ISTt7ALXVB8gTTF3OvItubk2E3v6sgirgtvdE5Mkd4MTJcO67bgdUCAwEAAaMhMB8wHQYDVR0OBBYEFEXiTeLGkA2LgAjQOrT2KChpgwCgMA0GCSqGSIb3DQEBCwUAA4IBAQA6GqtYZDQzym0yxfL2NnlSbJP/lLhSQOqbPBdN6DWQ/3duk+e08Ix5qy63hzW+qQR0PAkFEcooL5+bdheS66tFJpVejEcqCSKUVvwOUe6GY/ju752dlB7anBB9An362khehCxqydYNS5Igl0rtcP7dKC3ZBn1m2B9ULsyx46iNpfHQHHv9NKU2vVq2CtNc95CFktwjUwlyWMgbfI/DzPX/cC6KnglqsuVVBO7+jIaBmi0XGqudooZkqgIrvnfNMM13Gy78TUNHsCiAQEwZ/L17yNbzotNGxAoPfuXldbD52MQNOsA7WhH+j8qFWY6gZzTN4NpVtuW4m04TCEFexnTz
-----END CERTIFICATE-----
In case it's not visible above, there is a \n after -----BEGIN CERTIFICATE----- and before -----END CERTIFICATE-----
That public key got copied in the public key part of it, and in my code it's the public RSA key.
I also tried formatting using PKCS#1, I didn't get more success
It keeps being invalid. Not even expired, clearly invalid, both on jwt.io and in my code.
Assuming the token is correct, is my methodology correct? I found different tutorials preparing the .pem differently. If my token is incorrect, how can I check that aside of getting claims from it?
You need to generate the public key from modulus and exponent.
You can get them from https://login.microsoftonline.com/{tenantId_or_commom}/discovery/v2.0/keys
Here is a java sample for your reference:
public static PublicKey getPublicKey(String encodedModulus, String encodedExponent) throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] modulus = Base64.getUrlDecoder().decode(encodedModulus);
byte[] exponent = Base64.getUrlDecoder().decode(encodedExponent);
StringBuilder sb = new StringBuilder();
for (byte b : modulus) {
sb.append(String.format("%02x", b));
}
String sm = sb.toString();
sb = new StringBuilder();
for (byte b : exponent) {
sb.append(String.format("%02x", b));
}
String se = sb.toString();
BigInteger bm = new BigInteger(sm,16);
BigInteger be = new BigInteger(se,16);
KeyFactory rsa = KeyFactory.getInstance("RSA");
PublicKey publicKey = rsa.generatePublic(new RSAPublicKeySpec(bm, be));
return publicKey;
}
public static void main(String[] args) throws Exception {
String modulus = "0XhhwpmEpN-jDBapnzhFbtvEU2BpLLcaLzlXm4mlT2MwKZlXRUUam2vI0URDUYRKaa4O62BCWSSGOv2LGQ6tMD5oU-Dqkuf44bo1hLufIqAALUymssfRurTrLd0fqVA9ZCF3fA8_7xQi5r370m4h-G71ez8eE3lxiVPlwSeJXRpa5QzGA8ApwbXGiV-6liGU4eMXBU39A5rFy6TdioaC4P6xns-IdwlLMWdOR28P4O0yhbVTqcN_kW4N4AQonslB_tGOJGhWJjFkcqsQ8cbiJn6Q6FXoNADXohJO3sAtdUHyBNMXc68i25uTYTe_qyCKuC290TkyR3gxMlw7rtuB1Q";
String exponent = "AQAB";
byte[] bytes = getPublicKey(modulus, exponent).getEncoded();
String encodedString = new String(Base64.getEncoder().encode(bytes));
System.out.println("-----BEGIN PUBLIC KEY-----");
System.out.println(encodedString);
System.out.println("-----END PUBLIC KEY-----");
System.out.println();
}
You will get some outputs as following:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0XhhwpmEpN+jDBapnzhFbtvEU2BpLLcaLzlXm4mlT2MwKZlXRUUam2vI0URDUYRKaa4O62BCWSSGOv2LGQ6tMD5oU+Dqkuf44bo1hLufIqAALUymssfRurTrLd0fqVA9ZCF3fA8/7xQi5r370m4h+G71ez8eE3lxiVPlwSeJXRpa5QzGA8ApwbXGiV+6liGU4eMXBU39A5rFy6TdioaC4P6xns+IdwlLMWdOR28P4O0yhbVTqcN/kW4N4AQonslB/tGOJGhWJjFkcqsQ8cbiJn6Q6FXoNADXohJO3sAtdUHyBNMXc68i25uTYTe/qyCKuC290TkyR3gxMlw7rtuB1QIDAQAB
-----END PUBLIC KEY-----
And then you can use it in jwt.io:

C# DocuSignJWT SDK - invalid_grant

I keep getting an "invalid_grant" error when I try to use the DocuSign sdk to generate a JWT user token, and I can't figure out where I'm going wrong here...
public OAuthToken GetJwtToken(string userId)
{
try
{
var client = new ApiClient();
var authToken = client.RequestJWTUserToken
(
IntegrationKey,
userId,
BaseUrl,
Encoding.UTF8.GetBytes(PrivateKey),
1,
new List<string> { "signature", "impersonation" }
);
return authToken;
}
catch (ApiException e)
{
var msg = e.Message;
}
return null;
}
And the values:
<add key="IntegrationKey" value="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" />
<add key="PrivateKey" value="-----BEGIN RSA PRIVATE KEY-----\r\n\xxxxxxxxxxxx\r\n-----END RSA PRIVATE KEY-----" />
<add key="BaseUrl" value="account-d.docusign.com" />
I have a feeling it has something to do with the way the private key is coming in. I have it stored in the web config with \r\n for each new line, but if I try to just read it from the config file and pass it in, this line in the CreateRSAKeyFromPem() method throws a System.IO.IOException saying "-----END RSA PRIVATE KEY not found" unless I do a '.Replace("\r\n", "\r\n")' on the private key string:
object result = pemReader.ReadObject();
I've looked at every thread I can find, copied the example code for this, and quadruple checked all of my values. I have no idea why this won't work.
Edit: I pasted the assertion string that the code is sending in the request into https://jwt.io/ and I was able to verify that the decoded data is correct and the signature is verified after pasting in my public and private keys. I'm not sure why this wouldn't be working after checking all of that.
Edit 2: This is how I'm storing my RSA private key:
<add key="DocuSign:PrivateKey" value="-----BEGIN RSA PRIVATE KEY-----\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\nxxxxxxx\r\n-----END RSA PRIVATE KEY-----" />
and I'm retrieving it like this (System.IO throws this error if I try to grab the value without that Replace in there: "-----END RSA PRIVATE KEY not found")
public static string PrivateKey { get { return ConfigurationManager.AppSettings["DocuSign:PrivateKey"].Replace("\\r\\n", "\r\n"); } }
I ended up having to delete my RSA keypair for my app and generating a new one. The new key worked. I'm not sure why the old one didn't, but this resolved it at least.

Jose RSAPrivateKey and JsonWebKey Database Storage

I am trying to use Jose (https://bitbucket.org/b_c/jose4j/wiki/Home) to generate a signed JsonWebToken. I am running into a problem creating the RsaKeyPairs that I need to use in the signature of the token.
This is the code I am using to generate the public/private Keys and I need to turn this to String so I can store them in the database and then retrieve them.
WebKeyManager wkm = null;
Object obj;
EncryptionKey encKey = null;
RsaJsonWebKey rsaJsonWebKey = null;
try
{
wkm = new WebKeyManager();
int keySize = 512;
// Initialize KeyPairGenerator.
SecureRandom random = SecureRandom.getInstanceStrong(); //cryptographically strong random number generator
// Generate an RSA key pair, which will be used for signing and verification of the JWT, wrapped in a JWK
rsaJsonWebKey = RsaJwkGenerator.generateJwk(keySize, random.getProvider().getName(),random);
// Give the JWK a Key ID (kid), which is just the polite thing to do
rsaJsonWebKey.setKeyId(""+System.currentTimeMillis());
String json = rsaJsonWebKey.toJson(OutputControlLevel.INCLUDE_PRIVATE);
}
catch (Exception e)
{
e.printStackTrace();
}
The Problem I am Encountering is when I do rsaJsonWebKey.toJson(OutputControlLevel.INCLUDE_PRIVATE)
I get this error:
java.lang.ClassCastException: sun.security.mscapi.RSAPrivateKey cannot be cast to java.security.interfaces.RSAPrivateKey
at org.jose4j.jwk.RsaJsonWebKey.getRsaPrivateKey(RsaJsonWebKey.java:123)
at org.jose4j.jwk.RsaJsonWebKey.fillPrivateTypeSpecificParams(RsaJsonWebKey.java:135)
at org.jose4j.jwk.PublicJsonWebKey.fillTypeSpecificParams(PublicJsonWebKey.java:122)
at org.jose4j.jwk.JsonWebKey.toParams(JsonWebKey.java:166)
at org.jose4j.jwk.JsonWebKey.toJson(JsonWebKey.java:178)
I tried to debug the code in Jose and the error is in PublicJsonWebKey class this line:
protected void fillPrivateTypeSpecificParams(Map<String,Object> params)
{
RSAPrivateKey rsaPrivateKey = getRsaPrivateKey();
rsaPrivateKey is java.security.interfaces.RSAPrivateKey while getRsaPrivateKey() returns org.jose4j.jwk.RsaJsonWebKey
What am I doing wrong?
My requirement is to generate KeyPairs, store them in the database in varchar type field or something similar and then whenever needed, I can retrieve the String from the database, convert it back to private/public keys and use them to sign the token?
After some research, I found out that if I create the keys using this constructor
rsaJsonWebKey = RsaJwkGenerator.generateJwk(keySize);
then I don't get the error.

How can I generate a key pair and use it to sign and verify text in Node.js?

How can I generate a private and public key, use the private key to sign a hash of arbitrary text, then elsewhere use the public key to verify the signature?
Using URSA (Node.js wrappers for OpenSSL crypto):
var ursa = require('ursa');
// Generate RSA private key (public key included)
var keyPair = ursa.generatePrivateKey();
// Convert public key to string
var pub = keyPair.toPublicPem('base64');
// Create buffer from text
var data = new Buffer('Hello, world!');
// Create MD5 hash and sign with private key
var sig = keyPair.hashAndSign('md5', data);
// Elsewhere...
// Create public key object from PEM string
pub = ursa.createPublicKey(pub, 'base64');
// Verify signature - should return true
pub.hashAndVerify('md5', data, sig);

Resources