I'm generating Ed25519 key pairs in my Kotlin app using the BouncyCastle library and have two requirements that are easy to implement in isolation, but seemingly difficult to do in tandem:
Provide the key pair as a JCE KeyPair instance for use with a third-party SSH library
Provide the public key in OpenSSH .pub format for the user to copy and paste into a git repository provider such as GitHub (i.e. ssh-ed25519 <encoded key> <comment>)
I have two options for generating the keys using BouncyCastle, each makes only one of these requirements easy.
Generate directly using BouncyCastle generator
val generator = Ed25519KeyPairGenerator()
generator.init(Ed25519KeyGenerationParameters(SecureRandom()))
val pair = generator.generateKeyPair()
This gives me a key containing Ed25519PublicKeyParameters, which makes it super easy to get the OpenSSH .pub format using OpenSSHPublicKeyUtil provided by BouncyCastle:
"ssh-ed25519 " + toBase64(OpenSSHPublicKeyUtil.encodePublicKey(publicKey))
...but there is no obvious way to get to a JCE KeyPair from here. The BouncyCastle JCE implementation seems to use BCEdDSAPublicKey and BCEdDSAPrivateKey as wrapper classes for exactly this purpose, but their constructors are package-private.
Generate using BouncyCastle as a JCE security provider
Security.addProvider(BouncyCastleProvider())
val keyPairGenerator: KeyPairGenerator = KeyPairGenerator.getInstance(EdDSAParameterSpec.Ed25519, BouncyCastleProvider.PROVIDER_NAME)
keyPairGenerator.initialize(EdDSAParameterSpec(EdDSAParameterSpec.Ed25519), SecureRandom())
val pair = keyPairGenerator.generateKeyPair()
This gives me the JCE KeyPair I'm looking for, but no obvious way to convert it to OpenSSH .pub format. The answers in this RSA-specific question all only support DSA/RSA, or suggest libraries that also don't seem to be able to handle the Ed25519 keys. I have tried:
Apache SSHD
SSHJ
Jsch
What I think I need
Any one of:
A way to convert from BouncyCastle's AsymmetricCipherKeyPair to a JCE KeyPair
A way to get a Ed25519PublicKeyParameters instance from a BCEdDSAPublicKey wrapper so I can use BouncyCastle's OpenSSH utility method
Another way to output a BouncyCastle generated Ed25519 public key from a KeyPair in OpenSSH format
Another way/library to generate an Ed25519 keypair that will support my two requirements
Hack using reflection (wrapped into getter of extension property), following way #2 (get a Ed25519PublicKeyParameters instance from a BCEdDSAPublicKey):
val BCEdDSAPublicKey.pubKey
get() = BCEdDSAPublicKey::class.declaredMemberProperties
.find { it.returnType.javaType == AsymmetricKeyParameter::class.java }!!
.apply { isAccessible = true }
.get(this) as AsymmetricKeyParameter
I am trying to update to OpenSSL 1.1.1 from 1.0.2 and in doing so I have to convert some code. A lot of structures were made opaque in 1.1.0 and now need an accessor function. For the most part I have found something that works or a suitable workaround. However I can't seem to find any accessor function(s) or suitable way to convert the following code snippet from my code:
OBJ_obj2nid(request->sig_alg->algorithm)
Where "request" is a "X509_req_st" struct(in openssl typedefed to X509_REQ) and I want to access the sig_alg as seen in the openssl struct definition:
struct X509_req_st {
X509_REQ_INFO req_info; /* signed certificate request data */
X509_ALGOR sig_alg; /* signature algorithm */
ASN1_BIT_STRING *signature; /* signature */
CRYPTO_REF_COUNT references;
CRYPTO_RWLOCK *lock;
/* Set on live certificates for authentication purposes */
ASN1_OCTET_STRING *distinguishing_id;
};
And then access the algorithm as seen in the openssl X509_ALGOR struct definition
struct X509_algor_st {
ASN1_OBJECT *algorithm;
ASN1_TYPE *parameter;
};
I've have looked through the openssl project on github and especially the x509.h.in file where most of the accessor functions seem to be found as well as scoured the web but can't find how to do this. If there is no accessor function that can do this I'll greatly appreciate any suggestions on how I could approach this or perhaps how/where to .patch in my own accessor function.
Use X509_REQ_get_signature_nid to get the signature algorithm field. Internally, it is implemented using OBJ_obj2nid to the same member.
The equivalent function for X509 struct is also available in 1.0.2, but not the X509_REQ one.
So, in your case, the code should be:
int nid = X509_REQ_get_signature_nid(request)
You can refer this link for info:
https://www.openssl.org/docs/man1.1.1/man3/X509_REQ_get_signature_nid.html
I created a PDF PAdES signature and added a local computer timestamp ANS1/CMS Attribute signingTime. This works but is not valid by the ETSI online validator (Registration required)
I am aware that the ETSI Standard (page 19 table 1) defines that signingTime is not allowed.
Why is signingTime so bad? I do want an signed timestamp of the signature time (signed Attribute) so
What can I use instead (and conform to the standard)? content-time-stamp (signed) and signature-time-stamp (unsigned) seem to have a different meaning.
I do not want to use an TSP (Cryptographic timeserver).
signing-time is optional in CMS but it should not be used in PAdES. It should be included in the specific entry M in the Signature dictionary of the PDF document
See ETSI specification for testing PAdES signatures section 4.2 Testing CMS digital signatures in PDF
#PAdES/CMS/1
This is the simplest CMS digital signatures in PDF with minimum requirements and signature dictionary entry M (signing time).
Note that the signing-time is a reference of the date and time of signature obtained from the signer's device and can not be considered a reliable source of time.
content-time-stamp and signature-time-stamp are both RFC3161 time-stamp tokens. But content-time-stamp is computed before data is signed, and signature-time-stamp after the signature is generated and is an unsigned attribute. A signature including signature-time-stamp is a PAdES-T signature
See CAdES ETSI specification
content-time-stamp attribute is a time-stamp token of the signed data content before it is signed, and is included as part of the signature
signature-time-stamp attribute is a TimeStampToken computed on the signature value for a specific signer; it is an unsigned attribute.
I have the necessary components to build the private/public RSA key: N, E, D, P, & Q. I can derive the other values for the CRT if needed. How can I use these parameters to produce a valid Private/Public key in DER, PEM, or PKCS#7? It doesn't matter which to me as I can convert between them. I'm looking for a tool, library, script, or program that supports assigning these values and writing out a valid file, so I don't have to read hundreds of pages on ASN.1. Every tool I've looked at doesn't expose this use case in the API.
If you are using Java, there is the RSAPrivateKeySpec class, which takes BigInteger arguments of modulus and exponent. There are subclasses which take instead of N the P and Q primes (for more efficiency). You can then use a KeyFactory to convert this object to a Key, and then to some EncodedKeySpec class like PKCS8EncodedKeySpec or X509EncodedKeySpec.
You should be able to use OpenSSL (the library).
BIGNUM is described here. There are many functions to create a BIGNUM out of your input (depending on format). BN_bin2bn is probably the simplest, but hexadecimal or decimal input is also supported.
RSA is a structure that contains BIGNUMs. It's described here. You can initialise it yourself (directly).
You can then write the RSA structure using one of the PEM functions (described here). For example, PEM_write_RSAPrivateKey writes a PEM file containing a private key (you can also encrypt it, if you want to).
I'm not aware of any tool that does all of the above. Also, ASN.1 isn't so bad (a public/private key is pretty much a SEQUENCE of INTEGERs).
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
So after CodingHorror's fun with encryption and the thrashing comments, we are reconsidering doing our own encryption.
In this case, we need to pass some information that identifies a user to a 3rd party service which will then call back to a service on our website with the information plus a hash.
The 2nd service looks up info on that user and then passes it back to the 3rd party service.
We want to encrypt this user information going into the 3rd party service and decrypt it after it comes out. So it is not a long lived encryption.
On the coding horror article, Coda Hale recommended BouncyCastle and a high level abstraction in the library to do the encryption specific to a particular need.
My problem is that the BouncyCastle namespaces are huge and the documentation is non-existant. Can anyone point me to this high level abstraction library? (Or another option besides BouncyCastle?)
High level abstraction? I suppose the highest level abstractions in the Bouncy Castle library would include:
The BlockCipher interface (for symmetric ciphers)
The BufferedBlockCipher class
The AsymmetricBlockCipher interface
The BufferedAsymmetricBlockCipher class
The CipherParameters interface (for initializing the block ciphers and asymmetric block ciphers)
I am mostly familiar with the Java version of the library. Perhaps this code snippet will offer you a high enough abstraction for your purposes (example is using AES-256 encryption):
public byte[] encryptAES256(byte[] input, byte[] key) throws InvalidCipherTextException {
assert key.length == 32; // 32 bytes == 256 bits
CipherParameters cipherParameters = new KeyParameter(key);
/*
* A full list of BlockCiphers can be found at http://www.bouncycastle.org/docs/docs1.6/org/bouncycastle/crypto/BlockCipher.html
*/
BlockCipher blockCipher = new AESEngine();
/*
* Paddings available (http://www.bouncycastle.org/docs/docs1.6/org/bouncycastle/crypto/paddings/BlockCipherPadding.html):
* - ISO10126d2Padding
* - ISO7816d4Padding
* - PKCS7Padding
* - TBCPadding
* - X923Padding
* - ZeroBytePadding
*/
BlockCipherPadding blockCipherPadding = new ZeroBytePadding();
BufferedBlockCipher bufferedBlockCipher = new PaddedBufferedBlockCipher(blockCipher, blockCipherPadding);
return encrypt(input, bufferedBlockCipher, cipherParameters);
}
public byte[] encrypt(byte[] input, BufferedBlockCipher bufferedBlockCipher, CipherParameters cipherParameters) throws InvalidCipherTextException {
boolean forEncryption = true;
return process(input, bufferedBlockCipher, cipherParameters, forEncryption);
}
public byte[] decrypt(byte[] input, BufferedBlockCipher bufferedBlockCipher, CipherParameters cipherParameters) throws InvalidCipherTextException {
boolean forEncryption = false;
return process(input, bufferedBlockCipher, cipherParameters, forEncryption);
}
public byte[] process(byte[] input, BufferedBlockCipher bufferedBlockCipher, CipherParameters cipherParameters, boolean forEncryption) throws InvalidCipherTextException {
bufferedBlockCipher.init(forEncryption, cipherParameters);
int inputOffset = 0;
int inputLength = input.length;
int maximumOutputLength = bufferedBlockCipher.getOutputSize(inputLength);
byte[] output = new byte[maximumOutputLength];
int outputOffset = 0;
int outputLength = 0;
int bytesProcessed;
bytesProcessed = bufferedBlockCipher.processBytes(
input, inputOffset, inputLength,
output, outputOffset
);
outputOffset += bytesProcessed;
outputLength += bytesProcessed;
bytesProcessed = bufferedBlockCipher.doFinal(output, outputOffset);
outputOffset += bytesProcessed;
outputLength += bytesProcessed;
if (outputLength == output.length) {
return output;
} else {
byte[] truncatedOutput = new byte[outputLength];
System.arraycopy(
output, 0,
truncatedOutput, 0,
outputLength
);
return truncatedOutput;
}
}
Edit: Whoops, I just read the article you linked to. It sounds like he is talking about even higher level abstractions than I thought (e.g., "send a confidential message"). I am afraid I don't quite understand what he is getting at.
Assuming that you write your application in Java I'd recommend that you don't use a specific provider, but that you develop your application on top of Sun's JCE (Java Cryptography Extension). Doing so can make you independent of any underlying providers, I.e., you can switch providers easily as long as you use ciphers that are widely implemented. It does give you a certain level of abstraction as you don't have to know all the details of the implementations and may protect you a little from using the wrong classes (e.g. such as using raw encryption without proper padding etc) Furthermore, Sun provides a decent amount of documentation and code samples.
I've actually found that this sample uses default 128 bit encryption instead of 256 bit. I've made a little change:
BlockCipher blockCipher = new AESEngine();
now becomes:
BlockCipher blockCipher = new RijndaelEngine(256);
and it works together with my client application C++ AES256 encryption
One example of a high(er)-level API in BouncyCastle would be the CMS (Cryptographic Message Syntax) package. This ships in a separate jar (bcmail) from the provider itself, and is written to the JCE (The C# version is written against the lightweight API however).
"Send a confidential message" is implemented, roughly speaking, by the CMSEnvelopedDataGenerator class, and all you really need to do is give it the message, choose an encryption algorithm (all details handled internally), and then specify one or more ways that a recipient will be able to read the message: this can be based on a public key/certificate, a shared secret, a password, or even a key agreement protocol. You can have more than one recipient on a message, and you can mix and match types of recipient.
You can use CMSSignedDataGenerator to similarly send a verifiable message. If you want to sign and encrypt, the CMS structures are nestable/composable (but order could be important). There's also CMSCompressedDataGenerator and recently added CMSAuthenticatedData.
You may use:
byte[] process(bool encrypt, byte[] input, byte[] key)
{
var cipher = CipherUtilities.GetCipher("Blowfish");
cipher.Init(false, new KeyParameter(key));
return cipher.DoFinal(input);
}
// Encrypt:
byte[] encrypted = process(true, clear, key);
// Decrypt:
byte[] decrypted = process(false, encrypted, key);
See: https://github.com/wernight/decrypt-toolbox/blob/master/dtDecrypt/Program.cs
JCE won't work for me because we want 256 bit strength and can't change the java configuration on the system to allow it. Too bad the Bouncy Castle doesn't have an API as high-level as JCE.
"Note however that bouncycastle consists of two libraries, the lightweight crypto library and the JCE provider interface library. The keysize restrictions are enforced by the JCE layer, but you don't need to use this layer. If you just use the lightweight crypto API directly you don't have any restrictions, no matter what policy files are or are not installed."
http://www.coderanch.com/t/420255/Security/AES-cryptoPerms-Unlimited-Cryptography
The book Beginning Cryptography with Java contains very helpful examples and explanations based on the bouncycastle library