What is the correct type to attach a signature with sbattach? - signature

I'd like to clarify that whether sbattach can attach any signature or only the signature that is detached by using sbattach --detach method.
I've tried all of the signature types but either I'm getting:
PKCS7 verification failed for file test.p7s 140001588476928:error:2107507A:PKCS7 routines:PKCS7_verify:no content:../crypto/pkcs7/pk7_smime.c:229:
OR:
Unable to parse signature data in file: test.pkcs7
140520781806592:error:0D0680A8:asn1 encoding routines:asn1_check_tlen:wrong tag:../crypto/asn1/tasn_dec.c:1149: 140520781806592:error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:309:Type=PKCS7
I've tried to attach the signature that I created.

Related

Bad padding exception after encrypting a message with RSA SHA1 OAEP MGF1

I need to encrypt some message before sending it as request body in an API. I have to do this in Python and the library I used is Pycryptodome. From hereon, when I use the term API, I am referring to the API endpoint provided by the vendor and not the Pycryptodome API. The receiver(API vendor) shared the certificate (RSA 2048 bits) which I need to use to encrypt this message. This certificate is in binary format (DER) and has .cer as the extension. I need to import this using Pycryptodome and from the docs (https://pycryptodome.readthedocs.io/en/latest/src/public_key/rsa.html), I find that the import_key method accepts X.509 certificates in either binary or PEM encoding. The API documentation says I need to use RSA/NONE/OAEPWithSHA1AndMGF1Padding for encryption. This is my code.
def encrypt_message(message):
with open('/home/krishna/work/.certificates/random_certificate.cer', 'rb') as _file:
key_contents = _file.read()
recipient_key = RSA.import_key(key_contents)
cipher_rsa = PKCS1_OAEP.new(recipient_key)
return base64.b64encode(cipher_rsa.encrypt(message.encode())).decode()
I read the PKCS1_OAEP.py file, the default mask generation function is MGF1, default hash algorithm is SHA1. Hence, I did not specify these parameters in the new function in the above code. Also, I need to send this encrypted message as a base64 string (UTF-8). After reading the API documentation and the Pycryptodome documentation, I felt this code is sufficient for encryption. Also, this code is somewhat standard and is almost the same as the one in the Pycryptodome documentation. However, I get a decryption error and the vendor tells me this is due to "BAD PADDING EXCEPTION". This should not happen since I used OAEP for padding and the vendor confirmed they are using OAEP for padding as well. This is very hard for me to debug as I do not possess the vendor's private key.
So I tried generating my own pair of private and public keys (RSA-2048) and checked if I am able to decrypt my message. And duh, I am able to decrypt my message. Here is the code for encryption and decryption using my own keys.
def encrypt_message(message):
with open('my_pub.pem', 'rb') as _file:
pub = _file.read()
recipient_key = RSA.importKey(pub)
cipher_rsa = PKCS1_OAEP.new(recipient_key)
return base64.b64encode(cipher_rsa.encrypt(message.encode())).decode()
def decrypt_message(gibberish):
with open('my_priv.pem', 'rb') as _file:
priv = _file.read()
pvt_key = RSA.importKey(priv)
cipher_rsa = PKCS1_OAEP.new(pvt_key)
return cipher_rsa.decrypt(base64.b64decode(gibberish.encode())).decode()
So where I am going wrong? They key difference between this test and the actual API call is that my keys are generated in PEM format and have .pem as the extension. In the case of the API call, I have to use a .cer certificate in DER format. But I am assuming Pycryptodome is handling this for me (from the docs).
I have a few more questions regarding this.
What is NONE in RSA/NONE/OAEPWithSHA1AndMGF1Padding?
What is the difference between import_key() and importKey() in Pycryptodome? There are 2 methods and it does not look like importKey() has some documentation to it.
Can padding exceptions occur while using OAEP? From what I read from the internet, OAEP is the best method out there, not only in terms of adding randomness during encryption, but I also read that padding exceptions are very rare when this is used.
I really need to know what is going wrong here as I am dead clueless. Any suggestions or help will be appreciated.

GPG verify file and detached signature with given public key

I have a public key pubkey.asc.
Also I have a file file.txt and its detached signature file.txt.asc.
I want to check the following steps:
file.txt.asc is a signature for file.txt
file.txt.asc was created using secret key from a keyring with public key pubkey.asc
I can do the 1st step using gpg --verify file.txt.asc file.txt. This command outputs public key fingerprint which was used to create a signature:
gpg: Signature made <date and time>
gpg: using RSA key <fingerprint>
...
I can see pubkey.asc fingerprint just by running gpg pubkey.asc.
Can I use this information and just check if fingerprints are equal to perform 2nd step? If not, how can I verify a file signature with given public key?
I saw this question about how to verify if signature matches public key, but it only works if key has extension .gpg which is not my case.
OpenPGP key's fingerprint is a SHA1 hash of public key itself plus some additional data, and it uniquely identifies the key (excluding collision cases, which are not known yet for OpenPGP key fingerprints).
So, yeah, seeing 'good signature made by key [fingerprint]' is enough to rely on fact that signature is made by the aforementioned key.

Is sign output of the node.js/crypto module portable?

I'm trying to create a digital signature using the crypto.sign API of the node.js crypto module. I've confirmed that I can verify the signature by giving its output buffer to crypto.verify, but is it possible to verify this output with other software (e.g. signature libraries for other languages)?
settings:
Node.js version: v14
Signature algorithm (key) used: ed25519
const keyPair = await generateKeyPair('ed25519');
const signature = crypto.sign(null, Buffer.from('data'), keyPair.privateKey);
Public key exchange format: PEM
Signature data exchange format : Base64 encoding of crypto.sign output buffer (should be PKI's CMS or JWS standard format, but...)
What I'm wondering:
How should I handle the byte order when verifying base64 back to byte string in various languages?
What other things should I be aware of?

Amazon Seller Central MWS ListOrders GET request fails with "The request signature we calculated does not match the signature you provided."

I'm trying to make a GET call to pull orders from Amazon, but I keep getting the same signature error. I've googled around and I see that a lot of people appear to have this error, but none of their solutions seem to fix my issue. Any thoughts?
My request code:
$MWS_Timestamp=GetUTCFormattedDateTime(Date(Now_()),'UTC',false); // 2018-10-22T13:51:32Z
$MWS_AccessKey='AKIA****************';
$MWS_ClientSecret='ChOqu*************************';
$MWS_DeveloperID=798*********;
$MWS_SellerID='A3DL**********';
$MWS_MarketPlaceID='ATVP*********';
$MWS_AuthToken='amzn.mws.********-****-****-****-************';
$MWS_Action='ListOrders';
$MWS_RequestString="";
$MWS_RequestString+="AWSAccessKeyId="+UrlEncode($MWS_AccessKey,0);
$MWS_RequestString+="&Action="+UrlEncode("ListOrders",0);
$MWS_RequestString+="&LastUpdatedAfter="+UrlEncode('2018-10-21T00:00:00Z',0);
$MWS_RequestString+="&MarketplaceId.Id.1="+UrlEncode($MWS_MarketPlaceID,0);
$MWS_RequestString+="&SellerId="+UrlEncode($MWS_SellerID,0);
$MWS_RequestString+="&SignatureVersion="+UrlEncode("2",0);
$MWS_RequestString+="&SignatureMethod="+UrlEncode("HmacSHA1",0);
$MWS_RequestString+="&Timestamp="+UrlEncode($MWS_Timestamp,0);
$MWS_RequestString+="&Version=2013-09-01";
$MWS_SignatureString=$MWS_RequestString;
$signature='';
/* Creating signature with CryptoJS
var hmacsha1Data=CryptoJS.HmacSHA1($MWS_SignatureString,$MWS_ClientSecret); //Also tried $MWS_AccessKey with the same results
var base64EncodeData=CryptoJS.enc.Base64.stringify(hmacsha1Data);
$signature=encodeURIComponent(base64EncodeData);
*/
RunScript("<TAG>Scripts/JS-CryptoJS_v3.12</TAG>");
$signature=Replace($signature,"+","%2B");
$signature=Replace($signature,"/","%2F");
$signature=Replace($signature,"=","%3D");
$MWS_Request=$MWS_RequestString+"&Signature="+$signature;
$MWS_URL='https://mws.amazonservices.com/Orders/2013-09-01?'+$MWS_Request;
The Response:
<ErrorResponse xmlns="https://mws.amazonservices.com/Orders/2013-09-01">
<Error>
<Type>Sender</Type>
<Code>SignatureDoesNotMatch</Code>
<Message>
The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
</Message>
</Error>
<RequestID>54d6059b-9aa8-4d4f-a0b8-beb663599b25</RequestID>
</ErrorResponse>
I'm at a loss here as to which part is wrong. I double-checked the credentials, but everything looks good.
These parameters must all be appended in lexical order.
Here is one example where that isn't the case.
$MWS_RequestString+="&SellerId="+UrlEncode($MWS_SellerID,0);
$MWS_RequestString+="&LastUpdatedAfter="+UrlEncode('2018-10-21T00:00:00Z',0);
The order in the actual URL doesn't matter, but if you don't build them in this order then you won't calculate the right signature -- because the service will sort them before calculating the signature it expects you to send.
Also, your signature encoding is wrong.
$signature=Replace($signature,"+","%20")
There should be only 3 possibilities other than A-Z a-z 0-9:
+ becomes %2B
/ becomes %2F
= becomes %3D

signature error

This shows error "The request signature we calculated does not match the signature you provided. Check your AWS.
string url;
integer statuscode;
String date1=json.serialize(Datetime.now());
if(date1.contains('"')){
date1=date1.replace('"','');}
String algorithmName = 'HmacSHA256';
date1=date1.substring(0,(date1.length()-5));
date1=date1+'Z';
date1=EncodingUtil.UrlEncode(date1,'UTF-8');
String Action=EncodingUtil.UrlEncode('CreateTopic','UTF-8');
String AccessKey=EncodingUtil.UrlEncode('APIKEY','UTF-8'); // API key hide due to security resion but i check it work fine for SES
String Signaturemethod=EncodingUtil.UrlEncode('HmacSHA256','UTF-8');
string str= 'GET\nsns.us-east-1.amazonaws.com\n/\nAction='+Action+'&Name=Testtopics&AWSAccessKeyId='+AccessKey+'&Timestamp='+date1+'&SignatureVersion=2&SignatureMethod='+Signaturemethod;
Blob mac = Crypto.generateMac(algorithmName,Blob.valueOf(str),Blob.valueOf('SECURITYKEY')); //blob value of key used in signature
url='https://sns.us-east-1.amazonaws.com/?Action=CreateTopic&Name=Testtopics&AWSAccessKeyId=ACCESSKEY&Timestamp='+date1+'&SignatureVersion=2&SignatureMethod=HmacSHA256&Signature='+EncodingUtil.UrlEncode(EncodingUtil.base64Encode(mac),'UTF-8'); // final url
I don't have much Idea about the AWS but below is what I was able to find. can't test these things anywhere to figue out the problem.
A common cause of the error message below is not properly creating the string to sign, such as forgetting to URL encode characters such as the colon (:) and the forward slash (/) in Amazon S3 bucket names.
<Error>
<Type>Sender</Type>
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided.
Check your AWS Secret Access Key and signing method.
Consult the service documentation for details.</Message>
</Error>
http://docs.aws.amazon.com/general/latest/gr/signature-version-2.html
http://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html
It looks like you might be missing a trailing single quote at the end of your url. See if that makes a difference.
url="https://sns.us-east-1.amazonaws.com/?Action=CreateTopic&Name=Testtopics&AWSAccessKeyId=ACCESSKEY&Timestamp='+date1+'&SignatureVersion=2&SignatureMethod=HmacSHA256&Signature='+EncodingUtil.UrlEncode(EncodingUtil.base64Encode(mac),'UTF-8')+"'";

Resources