Padding mode not valid when try do decrypt a JWE payload with RSA-OAEP-256 and A256GCM - asp.net-core

I have no expertise with cryptography, i'm trying to decrypt a JWE payload in ASP.net core C#, the information that i have is the encryption was performed with RSA-OAEP-256 and A256GCM, so i'm using Jose libraries do deal with cryptography, the code is like:
eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0.rb3as5DV3PjfYM9cmxO1uE_OaLBt_gFMG9oe1iW_8999KNXEcxAuENaAJgD0fIWdrYD0UwDfkPxzG2cKy3SkvhQE5af7HNDuJBK7p_jjWZMNxtLO3IWCVbcYmH8r-TJEf4MPrDQi_0wP0QLIqH9aR3EVzRdkZ0tn1f8uSsaRlv7rXX_09mPME8V3y7dIDVAKJ0upvJvuyjnsNuAxXVAKvXjNdesKE_GMc3P5ZH6tOBb78a3uLyTOVf-itdR0f2Y7932QPnWbOM1d45mYARUK8Q28IHlKnyhntkA9YP8HQfvFdyMnAKhzPiybSU3Hg1U6wOh6qeYOqN4IIUedzZz__HFZZLpfPJHUacEXfgOWlPO3ZryMxN9v13pDG223oHl-9zbCOdtNsU3igOWlDM4094MECfpYWWem9cuEnbADjsyqVaq0l3CoL8MLUvDKpEjgI7ezopX0UFOlTWXjDxK-EmWeHOJlUAOjRJKUtmJBhiqtjY4quWsTO5xRzX-_fPyFw2Cql2T2_03FDNgZY6u8GpvmBR3f9E1jXqzNI36vbIdtBa6l0tksOPBnLeG070boMdViKMdUxAjzCW1EcUvaXo_vgOZ-ZU8_loOvGBOYmzE6myesQCMDaHXrSJROoR-G5lk5OO-hED6KWUptkqKI5vAuAHGuojq0_1d2YT4X4e8._jpZ8zc1XWIEFVmu.TKbdl02R_2q6-QwtW4cnUiNDoXhFX_fkTDxrhxofM8BhLTMhMk1cx3jvSPJADftBd5NgHghOouZePw_NwapFpNUwgFq__QvPVKcw6QQwU1IKcuh-ShfSJRtr9oVC93zQprZSvgLJsf5K-46sbjnEBc6dzCsL07r3M9fbg4XwaJyRW7iriLTXFbFEd-CbsqlGgZupHGUbn0W_h5PVYTuwAp4I7wyp_k2xF0i9MQRcLk04fm--zdwYo7-FfM3yfsz129OXzpH7tp6c_dl-5D53_cleLFLAIn1BNnDwVFfKIPkjbjz8_NzGoXWWESW8DP00Z2Of4qVgdhtBWunduriM7NyDWaiDWgePt3qX0A3nvSp6bIp9sXdZYiuGVM3z7-iMb-oJPsj1Abx5MuRHpbvovNLHY89QnV8Qf43TCUOGxpgiNcULd4QxeLn2NmXcmbxlFVxhGHxq44XHF0A14dEiWSYp4001T7lun-yv3DPZuiGiO-L4iKHZT-gnHAzjaDIyXVo5JsL1qWGVi59DJneQrnyjodZs7ESCUIbOASJ5SJ9QtSOu-uyvKVdyK6Tfw9-cGNXAzDBAOBmHcnxMOtWcZ6AscDJhpI_2quoktpTD9GkEM0gItKZ5W3r99i8t_RoZCakBdBY6D5gwVg4yFsJyb1YvqsYsH1X8MQBPdrVBTc4DUT0M0ucpfl5bV3nlMxxEffCyk-jbNNXid9_kOjq4Xv3-pHO4qJUQpJvRYIvGqyC0Ep1swo3-gbsUIjtEfyLlf2JkcDIM5WkV_iSvEbjch9lceTMKzjQVZgMnDWPvTtEvAZCXUxbRu9wE9fuX9F2W-yJ_DyB0o871IOhdDi0VyQcipQ2wkvuZecu9uqLFGtVk5NaPxYq0uOyaDQ3QzDwucAMwalaXPua9qjhLjM6TCePgn_ncVdN5jckMXo--RRAX3o4G1Hm8_xcJ6Amcvl8vsb7hUTdXY6um6CT-WDHbi-FQgMyyn-vlC64NJdngvT3uWvcKETS8UoKhp78nFDy20qWXIqSzxwi7rf60OL7vPZ_6McVfXORTbMjxvGRTT5skgkY58B5VPvB1c6vN12tKN3E3lqbJCpzass0rSzbfBxdRDg-PIV-Nuv0S-ch9aUxA5h6cMrYBZMQuiV-RO3EoqfQSU0JNGJuGir8mQAKuI5pJwROKrn1cCAaTSrcueobXz_ppJgZdxzjh_dUzZhfUrrE7DqJgPqHbuEPju7ViB39iPLsiniDz3W1iOhQKSbFDNzLmG_yzjKv1jF90onqIyo_mLN3kVlxHyvgP4MA8405OJCR_Cqmob0djhkiRsJCfNWUuVmmq0q0YPTfFIAn_R9A9Zdlwd8Ybg88_RKegLMwySgvfWT27w2OwGMQX6kCrPxV5pWS57lgmPiflq-R1H1uHXvBDoXySx3Uzv1J2ElzvtQGVufZFBznnirsQI87cwxSz76gWiVelf4GNJzRme3O1XRPhmlMlTBWCHOASRxTo9mM964oHc5g3cIRWrzNFppTV_FkJQ6cwPFYYjFdSA3Hh1w8_RxCxyXncsunAZoniCgV6KEBN7A5KybKMu424JQqWqdlKQqHBW7XLdqMnMH-ryzie22fGmIn4RrT5ha6ZI43rvLREt_4dYJJpmh4yw1f7Bh-8mIuKd1ha3lERWP0qZhSR6sSsCHob_UTe4JW_KwVT0om4FAgMzbLoKoZf1v01QHHn0ISSH9cvtgwv8TObcleMkEYrDJ_MxsSxOKm-B7VoKFDEhtns0ybZA_QYEK40voAzhrGO4CPjsOR7tWKIUFk3veNJRxmixBeGVP7Up7KAvXk7wAhRg060MzZ0Gf4kaWi6IS-H_hWSPYbb0NO0IQRcGYFXALt58p0hO61HpUqG5gnQGiceiMnj1DVKIVAbtnUhB_rGcrePPCKT_TQIeCyO4FRjtHw73iYePZgacVEJDGOqthPlVWJpKF9IWeUu5Ngqc3j6L75bQ4uuvUGVHAORbH3bzXoxxqx4hjU2kI0KvQwGs0VC6rCCgC2GCqJmn3-W0jxir9Mw3VBMaBOOpslv-FSMLriL4UX1solBR3pZ7bCm1vGCUooaj9tG0Pp4n6dwqGz54hkJ5vgYX5xEKZMYYJxhhKomRFNzvhJtli9qe4lNLUsMHEnwcs-BX1tMi7JSOxmPm5BNT_A7qYeRj4dJh4cR926geYdQpcXHhYC9qyNXuqsLG5Qf88rPqMeQerwBmxcwGbTUh2eUpSu4dZZzWuCUiG92Fb55UBtElxZ0mDsQ6SPso6g44oaBNaBbOJ1DnigSE6n1X-yz2HyRjYKHLCpbSHz2xDpQaHSUMVuHphOlS69Wn0Mwb_HljnQU0S34HJya1-zivBIDepkmt3_9EhLy3La872n3H1IEzkaNX7cjCr77imU2lQ32G1iwbFAo4FvJfkJhYwP2xLh1Q38GeE_2vsiQlu1iFr3Fs_Wxv-hYW6rnAz1B_1MSOI0slWMQywIhqZ7dbyyWv_S-oxecVneZ4LlSW-hxCYJGtrsGJtnEaRHVYZJ-N-MjwBm9nJU4P8mY9Nz9MPbWbovb8gJ5DLXFppZjReRk2A2zHTGKzav6Q0DYKI0NGmSDHJW6UbSjVzBBJe2r85NS4u5HGS_wyEhXXnMtJZdn6VBQj9AEY4Jrt2xZzCRoqWlUI46uMObvWq5qvkKCPcSLKyrHEIigbR3JmW3zzDNvc39RmiC6cbJ0Ypb-G0D4CNwdV2bemLzs29NIWms75cqMHxlkyKOqEX5UsYlGBhra_kM.vykYzq6TQ8ApQdyREGo6-g
var jwtSettings = new JwtSettings();
jwtSettings.RegisterMapper(new JwtPayloadConverter.JsonMapperJwt());
var decodedJwt = Jose.JWT.Decode(paylaodRetornoStone2, rsa, Jose.JweAlgorithm.RSA_OAEP_256, Jose.JweEncryption.A256GCM, jwtSettings);
when i try do decrypt the payload, i'm getting this error: specified padding mode is not valid for this algorithm.
the specific part of code that is throwing this exception is the:
byte[] cek = keyManagement.Unwrap(encryptedCek, key, jweAlgorithm.KeySize, header);
the implementation of RsaOaep256KeyManagement is doing this:
return Ensure.Type<RSA>(key, "RsaKeyManagement algorithm expects key to be of RSA type.").Decrypt(encryptedCek, RSAEncryptionPadding.OaepSHA256);
it seens that paddind mode is right, anyone have an idea to how fix this error?

Related

Error: bad secret key size while converting base58 secret key to uint8Array format

I am trying to convert my private key to uint8Array format. But I am getting "bad secret key size" error. Why? Here is my code:
const secretKey = bs58.decode("BxAN...RGM"); // secretKey: Uint8Array(32)
console.log(Web3.Keypair.fromSecretKey(secretKey));
It is a devnet phantom wallet address. I tried with different keys, but it still does not work.
I was incorrectly passing the public key as an argument instead of private key. The correct syntax is:
Web3.Keypair.fromSecretKey(secretKey);
Which caused Error: bad secret key size. You should pass the private key(in uint8Array format), not the public key.

XMPP SASL SCRAM-SHA1 Authentication

Recently, I was able to get MD5 authentication working for XMPP streams in Swift IOS following the instructions on the following two websites (I used the CC-MD5 function of Apple's CommonCrypto C library for the actual hashing):
http://wiki.xmpp.org/web/SASLandDIGEST-MD5
http://www.deusty.com/2007/09/example-please.html
I'm searching for a similar explanation for how to get other hashed SASL authentication schemes working, especially SCRAM-SHA1. I have found the official RFC5802 document but I'm having a lot of trouble understanding it (it is not specific to XMPP either). I would appreciate a simpler explanation or some simple readable code (C, PHP, C++, Javascript, Java) specific to XMPP authentication that doesn't use libraries for anything other than the actual hashing.
I'm interested in understanding the process and am not looking to use the ios XMPP-Framework. Any help would be appreciated.
SCRAM-SHA-1
The basic overview of how this mechanism works is:
The client sends the username it wants to authenticate as.
The server sends back the salt for that user and the number of iterations (either by generating them or looking them up in its database for the given username).
The client hashes the password with the given salt for the given number of iterations.
The client sends the result back.
The server does a variation of the hashing and sends it result back to the client, so the client can also verify that the server had the password/a hash of the password.
The cryptographic algorithms you'll need are SHA-1, HMAC with SHA-1 and PBKDF2 with SHA-1. You should look up how to use them in your language/framework, as I don't recommend implementing them from scratch.
In detail
First normalize the password (using SASLprep), this will be normalizedPassword. This is to ensure the UTF8 encoding can't contain variations of the same password.
Pick a random string (for example 32 hex encoded bytes). This will be clientNonce.
The initialMessage is "n=" .. username .. ",r=" .. clientNonce (I'm using .. for string concatenation).
The client prepends the GS2 header ("n,,") to the initialMessage and base64-encodes the result. It sends this as its first message:
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="SCRAM-SHA-1">
biwsbj1yb21lbyxyPTZkNDQyYjVkOWU1MWE3NDBmMzY5ZTNkY2VjZjMxNzhl
</auth>
The server responds with a challenge. The data of the challenge is base64 encoded:
<challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
cj02ZDQ0MmI1ZDllNTFhNzQwZjM2OWUzZGNlY2YzMTc4ZWMxMmIzOTg1YmJkNGE4ZTZmODE0YjQyMmFiNzY2NTczLHM9UVNYQ1IrUTZzZWs4YmY5MixpPTQwOTY=
</challenge>
The client base64 decodes it:
r=6d442b5d9e51a740f369e3dcecf3178ec12b3985bbd4a8e6f814b422ab766573,s=QSXCR+Q6sek8bf92,i=4096
The client parses this:
r= This is the serverNonce. The client MUST ensure that it starts with the clientNonce it sent in its initial message.
s= This is the salt, base64 encoded (yes, this is base64-encoded twice!)
i= This is the number of iterations, i.
The client computes:
clientFinalMessageBare = "c=biws,r=" .. serverNonce
saltedPassword = PBKDF2-SHA-1(normalizedPassword, salt, i)
clientKey = HMAC-SHA-1(saltedPassword, "Client Key")
storedKey = SHA-1(clientKey)
authMessage = initialMessage .. "," .. serverFirstMessage .. "," .. clientFinalMessageBare
clientSignature = HMAC-SHA-1(storedKey, authMessage)
clientProof = clientKey XOR clientSignature
serverKey = HMAC-SHA-1(saltedPassword, "Server Key")
serverSignature = HMAC-SHA-1(serverKey, authMessage)
clientFinalMessage = clientFinalMessageBare .. ",p=" .. base64(clientProof)
The client base64 encodes the clientFinalMessage and sends it as a response:
<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
Yz1iaXdzLHI9NmQ0NDJiNWQ5ZTUxYTc0MGYzNjllM2RjZWNmMzE3OGVjMTJiMzk4NWJiZDRhOGU2ZjgxNGI0MjJhYjc2NjU3MyxwPXlxbTcyWWxmc2hFTmpQUjFYeGFucG5IUVA4bz0=
</response>
If everything went well, you'll get a <success> response from the server:
<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
dj1wTk5ERlZFUXh1WHhDb1NFaVc4R0VaKzFSU289
</success>
Base64 decoded this contains:
v=pNNDFVEQxuXxCoSEiW8GEZ+1RSo=
The client MUST make sure the value of v is the base64 encoding of the serverSignature.
Extras
This is the basic version of the algorithm. You can extend it to do:
Channel binding. This mixes in some information from the TLS connection to the procedure to prevent MitM attacks.
Hashed storage. If the server always sends the same salt and i values, then the client can store only saltedPassword instead of the user's password. This is more secure (as the client doesn't need to store the password, just a hard to reverse salted hash) and faster, as the client doesn't need to do all the key stretching every time.
The server can also use hashed storage: the server can store only salt, i, storedKey and serverKey. More info on that here.
Possibly, also adding SCRAM-SHA-256 (though server support seems non-existent).
Pitfalls
Some common pitfalls:
Don't assume anything about the length of the nonces or salt (though if you generate them, make sure they are long enough and cryptographically random).
The salt is base64 encoded and can contain any data (embedded NULs).
Not using SASLprep may work fine for people using ASCII passwords, but it may completely break logging in for people using other scripts.
The initialMessage part of the authMessage does not include the GS2 header (in most situations, this is "n,,").
Test vectors
If you want to test your implementation, here are all the intermediate results for the example from the RFC:
Username: user
Password: pencil
Client generates the random nonce fyko+d2lbbFgONRv9qkxdawL
Initial message: n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL
Server generates the random nonce 3rfcNHYJY1ZVvWVs7j
Server replies: r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096
The salt (hex): 4125c247e43ab1e93c6dff76
Client final message bare: c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j
Salted password (hex): 1d96ee3a529b5a5f9e47c01f229a2cb8a6e15f7d
Client key (hex): e234c47bf6c36696dd6d852b99aaa2ba26555728
Stored key (hex): e9d94660c39d65c38fbad91c358f14da0eef2bd6
Auth message: n=user,r=fyko+d2lbbFgONRv9qkxdawL,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096,c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j
Client signature (hex): 5d7138c486b0bfabdf49e3e2da8bd6e5c79db613
Client proof (hex): bf45fcbf7073d93d022466c94321745fe1c8e13b
Server key (hex): 0fe09258b3ac852ba502cc62ba903eaacdbf7d31
Server signature (hex): ae617da6a57c4bbb2e0286568dae1d251905b0a4
Client final message: c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,p=v0X8v3Bz2T0CJGbJQyF0X+HI4Ts=
Server final message: v=rmF9pqV8S7suAoZWja4dJRkFsKQ=
Server's server signature (hex): ae617da6a57c4bbb2e0286568dae1d251905b0a4

Decrypt OpenSSL encrypted string in objective-c

I have a string encrypted in PHP using following code
function encrypt($string, $publicKey)
{
openssl_public_encrypt($string, $cryptedText, $publicKey);
return base64_encode($cryptedText);
}
$publicKey = file_get_contents('public.crt');
$encryptedText = encrypt('Test', $publicKey);
This works fine in PHP, i am able to encrypt/decrypt using public/private key pair.
The encryptedText is sent to iOS application where i want to decrypt the same string, i tried with multiple approaches and nothing seems to be working, any pointer to do the following is appreciated.
Decrypt OpenSSL encrypted string received from PHP in Objective-C
Encrypt and send data to PHP for Decrypting (should support openssl_private_decrypt)
I used this library for iOS which worked perfectly.
https://github.com/jslim89/RSA-Example

x509Certificate - Save a binary signature in pkcs#7 format (.net c#)

I am signing some data with a self signed X509Certificate in c#. Signature results as a binary byte[]. I want to save this signature to a pkcs#7 format file with extenstion .p7b. When I save this using FileStream as required. It generates an invalid p7b file.
Can anyone help save this signature as a valid external file? Or point out if there is something wrong with the approach?
// EDIT: Adding the code as asked by Eugene Mayevski
// Open Store Location & fetch certificate
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
X509Certificate2Collection certifcates = store.Certificates;
X509Certificate2 certificate = certifcates[0];`
// fetch private key
string publicKeyString = certificate.GetPublicKeyString();
RSACryptoServiceProvider privateKey = certificate.PrivateKey as RSACryptoServiceProvider;
// get binary of data & sign it.
byte[] buffer = Encoding.Default.GetBytes("Sample data to sign. Although it would be a document.");
byte[] signature = privateKey.SignData(buffer, new SHA1Managed());
You are not generating a Cryptographic Message Syntax (CMS) message format which is defined in PKCS#7. You generate just the signature, which can be placed in the container format.
To create a CMS formatted message yourself, please take a look at the Microsoft documentation or use the C# version of Bouncy Castle.

Authenticate in Xero from Salesforce

I'm new to Oauth and I stack on getting oauth_access_token to work with Xero. Web Service authentication doesn't work for me.
Xero returns the following error message "oauth_problem=signature_invalid&oauth_problem_advice=Failed to validate signature".
The generated signature is incorrect, but what is right way to generate it?
Here is APEX code which generates Endpoint. What is wrong?
Http h = new Http();
String consumer_key='XXX';
Long tmp=(System.now().getTime()/1000);
Blob isItCorrect = Crypto.generateMac('HMacSHA1', Blob.valueOf('https://api.xero.com/api.xro/2.0'), Blob.valueOf(consumer_key));
String signature= EncodingUtil.urlEncode(EncodingUtil.base64Encode(isItCorrect), 'UTF-8');
// Try to get access token
HttpRequest req = new HttpRequest();
req.setEndpoint('https://api.xero.com/oauth/RequestToken?oauth_consumer_key='+consumer_key+
'&oauth_signature_method=RSA-SHA1'+
'&oauth_signature='+signature+
'&oauth_timestamp='+tmp+ '&oauth_nonce='+tmp+'&oauth_version=1.0&scope=https%3A%2F%2Fapi.xero.com%2Fapi.xro%2F2.0');
req.setMethod('GET');
// Send the request, and return a response
HttpResponse res = h.send(req);
System.debug('~~~ '+res.getBody());
It generates following Endpoint:
Endpoint=https://api.xero.com/oauth/RequestToken?oauth_consumer_key=ICSP7Y5K2TG7RIIC6Y7R7KLC1AHWYC&oauth_signature_method=RSA-SHA1&oauth_signature=gWP02y2EIatw4xilTvd5Iq3e0%2Fw%3D&oauth_timestamp=1372123781&oauth_nonce=1372123781&oauth_version=1.0&scope=https%3A%2F%2Fapi.xero.com%2Fapi.xro%2F2.0
Just as an aside: I've never worked with salesforce so I'm not sure if there's a better
way to leverage existing oauth work on the platform, it's very rare
now to have to write all the oauth signature stuff yourself and it's
easy to make a mistake but here goes]
I think your signature base string is incorrect.
As far as I can tell you're just performing HMAC-SHA1 over https://api.xero.com/api.xro/2.0
if you read the OAuth Spec here: http://oauth.net/core/1.0/#anchor14 you need to construct the following base string (based on the request above)
GET&https%3A%2F%2Fapi.xero.com%2Foauth%2Frequesttoken&oauth_consumer_key%3DCONSUMER_KEY%26oauth_nonce (etc etc, just append all your query parameters apart from oauth_consumer as url encoded key=value pairs, in alphabetical order)
and then you need to create the hash with the key CONSUMER_KEY&CONSUMER_SECRET (both CONSUMER_KEY and CONSUMER_SECRET should be parameter encoded as per the OAuth Spec)
That should give you a valid signature..
Edit: I found this library which might be of help: https://code.google.com/p/sfdc-oauth-playground/