What algorithm does Verdaccio use to encrypt the npm registry? - encryption

Can't find the information anywhere. I'm a noob in computer security so my question might sound a bit dumb.
I understand we can communicate with Verdaccio using HTTPS and we can set up an authentication with htpasswd so I'm guessing a Verdaccio npm registry configured to use HTTPS and authentication is encrypted. If I'm right, what is/are the algorithm(s) used to encrypt the registry?

Verdaccio uses crypto.createCipher(algorithm, password[, options]) for encrypt by default tokens.
A simple example would be:
import { createDecipher, createCipher, createHash, pseudoRandomBytes, Hash } from 'crypto';
const const payload = Buffer.from(`${name}:${password}`, 'utf8'));
const c = createCipher('aes192', SOME_RANDOM_SALT_VALUE);
const b1 = c.update(payload);
const b2 = c.final();
return Buffer.concat([b1, b2]);
Furthermore, it has the option to use a standard JWT (jsonwebtoken), but it not enabled by default.
According the docs, the possible answer to your question might be
The algorithm is dependent on OpenSSL, examples are 'aes192', etc. On recent OpenSSL releases, openssl list -cipher-algorithms (openssl list-cipher-algorithms for older versions of OpenSSL) will display the available cipher algorithms.

Related

How should I sign a CSR using a signature created in HSM, in C# .NET Core?

I'm exhausted after looking for an answer for 3 days. I don't know if my suggested flow is wrong or my Google skills have really deteriorated.
My API needs to create a valid certificate from a CSR it received, by signing it with a private key that exists ONLY inside an HSM-like service (Azure KeyVault), which unfortunately doesn't offer Certificate Authority functions BUT does offer signing data with a key that exists there. My CA certificate's private key is stored in the HSM. I'm using ECDSA.
My suggested flow:
Client generates Key Pair + CSR and sends CSR to API
API creates a certificate from the CSR
API asks HSM to sign the CSR data and receives back a signature
API appends the signature to the certificate and returns a signed (and including CA in chain) certificate to the Client
I'm using C# .NET Core and would like to keep it cross-platform (as it runs in Linux containers), so I have to keep it as native as possible or using Bouncy Castle (which I'm still not sure if runs in Linux .NET Core).
I really appreciate your help!
I had faced a similar issue and found a solution. You'll have to use the PKCS11Interop.X509Store library.
The solution uses dotnet core native System.Security.Cryptography.X509Certificates.CertificateRequest::Create method
for generating a certificate.
As per the docs:
Pkcs11Interop is managed library written in C# that brings the
full power of PKCS#11 API to the .NET environment
Pkcs11Interop.X509Store is managed library built on top of
Pkcs11Interop. It's main goal is to provide easy to use PKCS#11 based
read-only X.509 certificate store that can be easily integrated with
standard .NET ecosystem.
Till v0.3.0, implementation for issuing a certificate (i.e signing a CSR) is not available.
With minor modifications in the PKCS11Interop library, I was able to sign the CSR.
Mentioned in Issue #30, the code is now added in the PKCS11Interop.X509Store library version 0.4.0.
The below code is taken from test cases for BasicEcdsaCertificateRequestTest. Test cases for RSA CertificateRequest are also there.
// Load PKCS#11 based store
using (var pkcs11Store = new Pkcs11X509Store(SoftHsm2Manager.LibraryPath, SoftHsm2Manager.PinProvider))
{
// Find signing certificate (CA certificate)
Pkcs11X509Certificate pkcs11CertOfCertificateAuthority = Helpers.GetCertificate(pkcs11Store, SoftHsm2Manager.Token1Label, SoftHsm2Manager.Token1TestUserEcdsaLabel);
// Generate new key pair for end entity
ECDsa ecKeyPairOfEndEntity = ECDsa.Create(ECCurve.NamedCurves.nistP256);
// Define certificate request
CertificateRequest certificateRequest = new CertificateRequest(
new X500DistinguishedName("C=SK,L=Bratislava,CN=BasicEcdsaCertificateRequestTest"),
ecKeyPairOfEndEntity,
HashAlgorithmName.SHA256);
// Define certificate extensions
certificateRequest.CertificateExtensions.Add(new X509BasicConstraintsExtension(false, false, 0, true));
certificateRequest.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(certificateRequest.PublicKey, false));
certificateRequest.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature, false));
// Issue X.509 certificate for end entity
X509Certificate2 certificateOfEndEntity = certificateRequest.Create(
pkcs11CertOfCertificateAuthority.Info.ParsedCertificate.SubjectName,
X509SignatureGenerator.CreateForECDsa(pkcs11CertOfCertificateAuthority.GetECDsaPrivateKey()),
DateTimeOffset.UtcNow,
DateTimeOffset.UtcNow.AddDays(365),
new BigInteger(1).ToByteArray());
// Verify signature on X.509 certificate for end entity
Assert.IsTrue(CaCertSignedEndEntityCert(pkcs11CertOfCertificateAuthority.Info.ParsedCertificate.RawData, certificateOfEndEntity.RawData));
// Asociate end entity certificate with its private key
certificateOfEndEntity = certificateOfEndEntity.CopyWithPrivateKey(ecKeyPairOfEndEntity);
// Export end entity certificate to PKCS#12 file
string basePath = Helpers.GetBasePath();
string pkcs12FilePath = Path.Combine(basePath, "BasicEcdsaCertificateRequestTest.p12");
File.WriteAllBytes(pkcs12FilePath, certificateOfEndEntity.Export(X509ContentType.Pkcs12, "password"));
}
Hope this helps.

How to decrypt file from Google Cloud Storage?

I have an encrypted file stored in a Google Cloud Storage bucket that was generated with the following command line:
gcloud kms encrypt --location=global --keyring=my-keyring --key=-my-key --plaintext-file=my-file --ciphertext-file=my-file.enc
I am now trying to decrypt such file in a Cloud Run service with the following code:
const kms = require('#google-cloud/kms');
const client = new kms.KeyManagementServiceClient();
const file = storage.bucket("my-bucket").file('my-file.enc');
const name = client.cryptoKeyPath( 'projectId', 'global', 'my-keyring', 'my-key' );
let encrypted = (await file.download())[0];
const [result] = await client.decrypt({name, encrypted });
I am getting the following error:
Error: Decryption failed: verify that 'name' refers to the correct CryptoKey.
Which, according to this, is misleading and should be considered as not being properly deciphered. I cannot shake the feeling that I am missing a base64 encode/decode somewhere but I don't seem to find the solution.
If I run the decryption from the command-line it works just fine.
Any help is very appreciated.
Thanks.
EDIT:
Problem solved thanks to this awesome community. Here goes the steps to make this work, in case others face the same issue:
Encrypt the file using the following command line and upload it via the web UI.
gcloud kms encrypt --location=global --keyring=my-keyring --key=-my-key --plaintext-file=my-file --ciphertext-file=my-file.enc
Decrypt using the following code:
const kms = require('#google-cloud/kms');
const client = new kms.KeyManagementServiceClient();
const file = storage.bucket("my-bucket").file('my-file.enc');
const name = client.cryptoKeyPath( 'projectId', 'global', 'my-keyring', 'my-key' );
let encrypted = (await file.download())[0];
const ciphertext = encrypted .toString('base64');
const [result] = await client.decrypt({name, ciphertext});
console.log(Buffer.from(result.plaintext, 'base64').toString('utf8'))
I spot a few things here:
Assuming your command is correct, my-file-enc should be my-file.enc instead (dot vs dash)
Verify that projectId is being set correctly. If you're populating this from an environment variable, console.log and make sure it matches the project in which you created the KMS key. gcloud defaults to a project (you can figure out which project by running gcloud config list and checking the core/project attribute). If you created the key in project foo, but your Cloud Run service is looking in project bar, it will fail.
When using --ciphertext-file to write to a file, the data is not base64 encoded. However, you are creating a binary file. How are you uploading that binary string to Cloud Storage? The most probable culprit seems to be an encoding problem (ASCII vs UTF) which could cause the decryption to fail. Make sure you are writing and reading the file as binary.
Looking at the Cloud KMS Nodejs documentation, it specifies that the ciphertext should be "exactly as returned from the encrypt call". The documentation says that the KMS response is a base64 encoded string, so you could try base64 encoding your data in your Cloud Run service before sending it to Cloud KMS for decryption:
let encrypted = (await file.download())[0];
let encryptedEncoded = encrypted.toString('base64');
const [result] = await client.decrypt({name, encrypted});
You may want to take a look at Berglas, which automates this process. There are really good examples for Cloud Run with node.
For more patterns, check out Secrets in Serverless.

Unable to decrypt the encrypted value in crypto-js using crypto-js in ionic3 app

-I have successfully carried out the encryption part of the username and --
-password value using crypto-js in the ionic v3 app for capturing it into -firebase-analytics.
import { Component, Input } from "#angular/core";
class Model {
param1: string;
value:any;
myPassword = "my message 123";
function decrypt(this.someuservalue:any,this.somemailid:any){
const encrypted = CryptoJS.AES.encrypt(this.someuservalue,
myPassword).toString();
}
}
-have obtained encrypted values in the firebase database as well.
-But now to decrypt it in another independent javascript file I'm not able to do it.
-Here is how I'm trying to decrypt it
var decrypted = CryptoJS.AES.decrypt(cipher, value);
var plaintext = = decrypted.toString(CryptoJS.enc.Utf8);
-But I'm unable to do so,
-Any help can be greatly appreciated.
-Thanks,
-I've tried
var cipher = "encrypted value from the above implemented encryption"
password = "my message 123";
var rawData = atob(cipher);
var iv = btoa(rawData.substring(0,16));
var crypttext = btoa(rawData.substring(16));
var plaintextArray = CryptoJS.AES.decrypt(
{
ciphertext: CryptoJS.enc.Base64.parse(crypttext),
salt: ""
},
CryptoJS.enc.Hex.parse(password),
{ iv: CryptoJS.enc.Base64.parse(iv) }
);
-and
var bytes = CryptoJS.AES.decrypt({
ciphertext: CryptoJS.enc.Utf8.parse(cipher)
}, password, {format: CryptoJS.format.Utf8 });
var plaintext = bytes.toString();
-both didn't seem to work.
Take a look at Sodium (libsodium.js).
Sodium is a modern, easy-to-use software library for encryption, decryption, signatures, password hashing and more.
It is a portable, cross-compilable, installable, packageable fork of NaCl, with a compatible API, and an extended API to improve usability even further.
Its goal is to provide all of the core operations needed to build higher-level cryptographic tools.
Sodium is cross-platforms and cross-languages. It runs on a variety of compilers and operating systems, including Windows (with MinGW or Visual Studio, x86 and x86_64), iOS and Android. Javascript and WebAssembly versions are also available and are fully supported. Bindings for all common programming languages are available and well-supported.
The design choices emphasize security and ease of use. But despite the emphasis on high security, primitives are faster across-the-board than most implementations.
Version 1.0.17 was released on January 7, 2019.
Ref:
Sodium GitBook
List of awesome JavaScript Crypto Libraries
JavaScript Crypto Libraries

PAW Rest Client: Generating HMAC-SHA256 Signature for AWS requests

I cannot successfully generate a signature for making AWS Requests using PAW.
Here is a link to the signature I am attempting to generate: http://docs.aws.amazon.com/AWSECommerceService/latest/DG/HMACSignatures.html#HMACAuth_ItemsRequired
I have already searched other StackOverflow posts such as: Paw rest client : how to compute HMAC-SHA256 using absolute url as input
To answer your precise question about HMAC-SHA256 signatures, here's a code snippet that will work to compute this specific type of signature, returning the result Base 64 encoded in Paw (it uses the HMAC Dynamic Value programmatically):
function signHmac256(input, key) {
var dv = DynamicValue("com.luckymarmot.HMACDynamicValue", {
input: input,
key: key,
algorithm: 3 /* = SHA256 */,
uppercase: false /* keep hashes lowercase */,
encoding: 'Base64' /* encode hash data in base 64 */,
});
return dv.getEvaluatedString();
}
Otherwise, about the AWS Product Advertising API, we've made a dynamic value for it just today (which is a good opportunity for use to showcase the extension API), see AWS Product Advertising API Auth for Paw and the GitHub Repository here.
To use this dynamic value, first install it through the link shared above, then you can set up all other parameters and then enter a Signature parameter, and set this dynamic value as its value:
Open the token to enter your AWS Secret Key (used in the HMAC signature):

WCF Certificate Authentication without installing on the Client

Our setup includes a WCF service and a number of clients written by us. Some of the clients include Silverlight applications, whereas others include Web and Windows applications.
I (think) I would like to authenticate clients based on X.509 certificates. Typically you would install a private key on the client to encrypt (aka digitaly sign) the messages. The server can the use the clients public key to de-crypt it to ensure the message has not been changed and prove the message is from who we expect (aka authenticated).
I dont want to install a certificate on a client machine. Its a hassel to deploy, and we cant really ask our clients to do it. I was speaking to someone the other day who sugested embeding the cert in a client assembly, reading it and using that. Is that possible?
It would be great if someone could point me to an example.
Thanks in advance,
David
Yes, you can load X509certificate2 by passing a certificate byte array with a password like
var certificate = new X509Certificate2(theByteArrary, "password");
To get the certificate byte array, you can simply copy paste the contents in .pfx file, which is a combination of .cer (public key) and .pvk (private key)
and then you can load this certificate on your client by doing:
var channelFactory = new ChannelFactory<IYourService>();
channelFactory.Credentials.ClientCertificate.Certificate =
clientCertificate;
If you use auto-generated client proxy, or you prefer configure the certificate via .config file then you might want to have a look at this from codeproject
Here is a suggestion. Could also be tweaked to use an embedded certificate.
http://www.codeproject.com/KB/WCF/wcfcertificates.aspx

Resources