I'm trying to use Bouncy Castle in approved mode (CryptoServicesRegistrar.SetApprovedOnlyMode(true);) and am having some trouble generating RSA keys. I keep throwing exceptions on the following line.
var generator = CryptoServicesRegistrar.CreateGenerator(new FipsRsa.KeyGenerationParameters(BigInteger.ValueOf(65537L), 3072), FipsSecureRandom.GetInstance(FipsDrbg.CtrAes256.Algorithm.Name));
I have debugged the constructor, looked at the source code, and so on, but I can't figure out how to get an FSR object. All the builder methods for the object are internal to the BC library so I can't get to them. The methods provided in the FipsDrbg class are all internal as well and the provided stubs (such as CtrAes256 in my example) don't expose it either. I've tried passing a string of a PRNG method directly to the constructor from the values I've found in the documentation such as "SHA256PRNG." This gives the following exception:
attempt to create key pair with unapproved RNG: RSA
Looking in the source, the method throwing this exception comes from a ValidateRandom method that checks to make sure the random instance is a FipsSecureRandom so it doesn't get me anywhere.
Lastly, trying to backtrack the Builder : IDrbgBuilder<FipsSecureRandom> class doesn't lead anywhere. They're wholly used in the Base : Org.BouncyCastle.Crypto.Parameters.Parameters<FipsAlgorithm>, IDrbgBuilderService<FipsSecureRandom> class which is completely internal. While the Builder's Build method is public, it's not static and the constructor is internal so I can't create an instance of it to build anything.
What am I missing?
Update:
I was asked to split out the failing line so here is that line split.
var rsaParams = new FipsRsa.KeyGenerationParameters(BigInteger.ValueOf(65537L), 3072);
var fipsRandom = FipsSecureRandom.GetInstance("SHA256PRNG");
var generator = CryptoServicesRegistrar.CreateGenerator(rsaParams, fipsRandom);
The line throwing the exception is the var generator = line. The full exception details are such.
Source: "bc-fips-1.0.1"
Message: attempt to create key pair with unapproved RNG: RSA
at Org.BouncyCastle.Crypto.Fips.Utils.ValidateRandom(SecureRandom random, Int32 securityStrength, FipsAlgorithm algorithm, String message)
at Org.BouncyCastle.Crypto.Fips.FipsRsa.KeyPairGenerator..ctor(KeyGenerationParameters keyGenParameters, SecureRandom random)
at Org.BouncyCastle.Crypto.Fips.FipsRsa.KeyGenerationParameters.<>c.<Org.BouncyCastle.Crypto.IGenerationService<Org.BouncyCastle.Crypto.Fips.FipsRsa.KeyPairGenerator>.GetFunc>b__17_0(IParameters`1 parameters, SecureRandom random)
at Org.BouncyCastle.Security.SecurityContext.CreateGenerator[A](IGenerationServiceType`1 type, SecureRandom random)
at Org.BouncyCastle.Crypto.CryptoServicesRegistrar.CreateGenerator[A](IGenerationServiceType`1 type, SecureRandom random)
No inner exception, no exception data.
Related
To sign data, I am using signserver open-source code. I was exploring a legacy code where
it gives error at this place:
Module.getPKCS11Module().C_FindObjectsInit(session.getSessionHandle(), attributes,true);
where the Module class is from iaikpkcs11Wrapper.jar (package: iaik.pkcs.pkcs11)
As I navigate further, PKCS11 interface has this method void C_FindObjectsInit(long var1, CK_ATTRIBUTE[] var3, boolean var4) mentioned above.
Moreover, the attributes param is constructed like below:
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTEKeyStoreContainerBase[2];
attributes[0] = new CK_ATTRIBUTE();
attributes[0].type = PKCS11Constants.CKA_CLASS;
attributes[0].pValue = new Long(PKCS11Constants.CKO_SECRET_KEY);
attributes[1] = new CK_ATTRIBUTE();
attributes[1].type = PKCS11Constants.CKA_ID;
attributes[1].pValue = id; //id is byteArray. For this param's value the error is causing
My question is, do I need to store any kind of key/certificate from where C_FindObjectsInit(..) will read or match as it says that it couldn't find any key? Where does this method search the key or how to resolve this issue?
Btw, I have read C_FindObjectsInit-JavaDoc and couldn't understand this line properly, that's why I am here:
pTemplate - the object's attribute values to match and the number of
attributes in search template (PKCS#11 param: CK_ATTRIBUTE_PTR
pTemplate, CK_ULONG ulCount)
[this may sound peculiar question, but I am really blank and stuck for few days]
PKCS#11 specification don't force us to use some strictly composed data.
But in most implementations I saw it was binary encoded OID field.
Also check for 0 (null) bytes in sequence.
I have some codebase that uses TLS and it works with the actual cipher processing via the integer value of the cipher selected. The selected cipher is extracted as follows:
String cipherSuite = sslSocket.getSession().getCipherSuite();
which is a value like TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, and has an integer value of 49200 or 0xc030 in hex. The codebase has a manually defined mapping class that returns the integer value of the cipher given the cipher name.
I took a look at the SSLSocket object chain there from an IDE to see what other methods were available, but didn't find anything that could do the lookup that the manual mapped class did.
From another faintly related SO post online, I found a table of TLS ciphers and their values: https://web.archive.org/web/20151219054439/http://www.thesprawl.org/research/tls-and-ssl-cipher-suites/.
Now I'm just wondering rather than go through the effort in maintaining the full table mapping, in case things change in future, is there already some Java class that we can call to do the lookup? e.g. lookup by cipher name to get integer/hex value or vice versa? I'm no security expert nor a Java guru, so wouldn't know.
P.S. the codebase I was working with didn't have the full mapping of the table link I mentioned, only a partial subset. Came across this problem as the codebase was failing from missing some ciphers that were now being used in the system. I added the missing ciphers, but looking for a more elegant way to maintain the cipher mapping or lookup.
You can get the standard TLS ciphersuite code for an existing session. You are vague how you "took a look ... from an IDE" but if you look with a debugger you should see that the SSLSessionImpl for the socket (or engine) contains cipherSuite which in turn contains both int id (the code) and String name (the name), although the API for SSLSession returns only the latter. For example in my Eclipse:
Since these classes and their fields (and methods) are not public you can't access them directly, but at least through j8 you can do so with reflection:
SSLSocket sock = (SSLSocket) SSLSocketFactory.getDefault().createSocket("example.com", 443);
SSLSession sess = sock.getSession(); // actually sun.security.ssl.SSLSessionImpl
Class<?> c1 = Class.forName("sun.security.ssl.SSLSessionImpl");
Field f1 = c1.getDeclaredField("cipherSuite"); f1.setAccessible(true);
Object cs = f1.get(sess);
Class<?> c2 = Class.forName("sun.security.ssl.CipherSuite");
Field f2 = c2.getDeclaredField("id"); f2.setAccessible(true);
Integer id = (Integer) f2.get(cs);
System.out.printf("%x%n", id);
In the 'module' scheme of j9 up this gives a warning for 'illegal reflective access', although so far (up to 13.0.1) it does actually succeed. If I get a better handle on exactly how modules work I will try to improve this. (Or this being Stack, someone else can.)
Note this doesn't actually provide a mapping as you asked, only the value for the current connection which appears to be your actual need. If you really want a mapping, CipherSuite is actually an enum class so all of the instances are in fact there, but looking at the code it appears the method used to find this mapping has been changed in different versions, as well as being nonpublic, so I'm not going to the trouble of trying to work out multiple examples without knowing which if any you need.
I would like to use my PKCS#11 enabled device as a source of SecureRandom.
So I have done the following:
Provider pkcs11provider = new sun.security.pkcs11.SunPKCS11(pkcs11config);
Security.addProvider(pkcs11provider);
byte[] rb = new byte[100];
SecureRandom sr = SecureRandom.getInstance("PKCS11", pkcs11provider);
sr.nextBytes(rb);
And I always get an exception:
Exception in thread "main" java.security.NoSuchAlgorithmException: no such algorithm: PKCS11 for provider SunPKCS11-HSM
at sun.security.jca.GetInstance.getService(GetInstance.java:101)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:218)
at java.security.SecureRandom.getInstance(SecureRandom.java:383)
What I am doing wrong? According JDK PKCS#11 Reference Guide "PKCS11" should be supported algorithm for SecureRandom.
"PKCS11" doesn't sound like an algorithm name. It is the provider name. A provider can have their own algorithm names for specific crypto operations. To see what all algorithms they have, you can run this code snippet to see them.
Set<Provider.Service> services = pkcs11provider.getServices();
services.forEach(service ->
{
// System.out.println(service.getType()); // --> Look for 'SecureRandom' type
System.out.println(service.getAlgorithm());
});
Look for 'SecureRandom' type, and that's the algorithm you have to pass in as the first argument in SecureRandom.getInstance(.., ..).
I'm trying to read the public certificate names from a smartcard to display to the user before they sign a file using a gemalto smartcard.
I've followed the getInfo example from iaikPkcs11Wrapper demos as below :
Module pkcs11Module = Module.getInstance(settings.getCryptoDll());
Slot[] slotList;
try{
slotList = pkcs11Module.getSlotList(true);
}catch(TokenException tex){//module is not initialised
tex.printStackTrace();
pkcs11Module.initialize(new DefaultInitializeArgs());
slotList = pkcs11Module.getSlotList(true);
}
for (Slot slot : slotList) {
Token token = slot.getToken();
iaik.pkcs.pkcs11.Session session = token.openSession(true, SessionReadWriteBehavior.RO_SESSION, null, null);
session.findObjectsInit(null);
Object[] objects = new Object[0];
try {
objects = session.findObjects(1);
This fails always at the line objects = findObjects(1); with a CKR_TEMPLATE_INCONSISTENT exception.
As I understand from the documentation session.findObjectsInit(null) should just return all accessible objects on the card and you can then compare them for type.
I have various smartcards and they all fail like this, I've also tried calling session.findObjectsInit(tempObj) with a GenericTemplate object and a X509PublicKeyCertificate which both return the same exception, and with an X509AttributeCertificate which returns no objects but does not throw the exception.
I'd appreciate any pointers anyone can give. Or do I need to create a matching template object using GenericTemplate? I'm unsure why I'm getting the exception as I thought passing the object into the getObjectInit method filtered for thet object so anything returned should match.
EDIT
I've subsequently tried with other templates and ones for objects not on the card just return an empty array- no exception and ones I think are on the cards just throw the ckr_template_inconsistent exception, any help would be gratefully received.
EDIT2
I've now tried with some new 'V3' cards, which do infact work, all my test cards work using another technique (we currently use capicom via com4J for signing), so maybe there is an issue with the iaik wrapper, or gclib.dll (or me).
We are using some org.apache classes as part of implementing WS Security for a webservice.
variables.paths = arrayNew(1);
variables.paths[1] = getDirectoryFromPath(getCurrentTemplatePath()) & "lib\wss4j-1.5.8.jar";
variables.paths[2] = getDirectoryFromPath(getCurrentTemplatePath()) & "lib\xmlsec-1.4.2.jar";
variables.loader = createObject("component","lib.javaloader.JavaLoader").init(loadPaths=variables.paths,loadColdFusionClassPath=true);
variables.WSConstantsObj = loader.create("org.apache.ws.security.WSConstants");
variables.messageClass = loader.create("org.apache.ws.security.message.WSSecUsernameToken");
variables.secHeaderClass = loader.create("org.apache.ws.security.message.WSSecHeader");
The following code:
<cfset var msg = getMessage()>
produces:
The following code:
<cfset var secHeader = getSecHeader()>
produces:
The following code:
<cfset var env = soapEnv.getDocumentElement()>
produces:
env.getOwnerDocument()
produces a huge structure (too big to include here), which you can view here.
However, the following code:
<cfset e = msg.build(env.GetOwnerDocument(),secHeader)>
throws the error:
The build method was not found.
Either there are no methods with the specified method name and argument types or the build method is overloaded with argument types that ColdFusion cannot decipher reliably. ColdFusion found 0 methods that match the provided arguments. If this is a Java object and you verified that the method exists, use the javacast function to reduce ambiguity.
However the Build() method certainly exists, as per the yellow highlight in the first screenshot.
The error message talks about "...use the javacast function to reduce ambiguity". If this were the problem, how would I apply this solution?
It's not that "build()" doesn't exist but that your signature is incorrect. The 2 arguments for the build method are:
env.GetOwnerDocument(),secHeader
We know that that secHeader is of the class
org.apache.ws.security.message.WSSecHeader
Because your cfdump indicates as much.
That likely means that "env.GetOwnerDocument" is not returning an object of the class
org.w3c.dom.Document
It may be returning an error or a primitive or another class. Instantiate envGetOwnerDocumet() and dump that out and check the class. I think it is screwing up the method signature. That's my best guess anyway.