In my C++ program I created a public/private key pair using CryptoAPI.
CryptGenKey(eTokenProv,ENCRYPT_ALGORITHM,CRYPT_EXPORTABLE,&k1)
Keys are stored in a eToken.
Is it possible to get the public key using PKCS#11? The private key previously created is found after a search using the following search-template:
CK_ATTRIBUTE private_search[] = {
{CKA_PRIVATE, CK_TRUE, sizeof(CK_BBOOL)}
};
If I set CKA_PRIVATE to CK_FALSE, I can't get the public key. I also tried with other attributes.
Is there a way to do it?
EDIT
As owlstead suggests, I tried to create a public key starting from the modulus and public exponent of a key created in a previous session (in CAPI or, just for this test, in PKCS11). I got the modulus and public exponent from a private key in these buffers:
CK_BYTE modulus[128]; //if 1024bit
CK_BYTE publicExponent[4]; //4 Byte, according to public key blob
But when I try to create a new public with key with the following instructions:
CK_ATTRIBUTE publicKeyTemplate[] = {
{CKA_TOKEN, &yes, sizeof(true)},
{CKA_WRAP, &yes, sizeof(true)},
{CKA_ENCRYPT, &yes, sizeof(true)},
{CKA_MODULUS_BITS, &modulusBits, sizeof(modulusBits)},
{CKA_MODULUS, &modulus, sizeof(modulus)},
{CKA_PUBLIC_EXPONENT, &publicExponent, sizeof(publicExponent)}
CK_MECHANISM mechanism = {CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
rv = (*functions->C_GenerateKeyPair) (session, &mechanism, publicKeyTemplate, 6, privateKeyTemplate, 6, &hPublicKey, &hPrivateKey);
I get the error "Invalid template". The probles is the modulus, because, without it, I can create a key pair. I use the function C_GenerateKeyPair, but I'm only interested in the public key. I omitted the private template.
What is the wrong here?
CKA_PRIVATE does not indicate a private key at all.
When the CKA_PRIVATE attribute is TRUE, a user may not access the object until the user
has been authenticated to the token
Instead you should look for an attribute such as CKA_CLASS with a value CKO_PUBLIC_KEY or CKO_PRIVATE_KEY, possibly using other attributes to filter your results further.
If you cannot find any CKO_PUBLIC_KEY then I presume it was either not generated in the token (key was imported, check if CKA_LOCAL is set). Alternatively, it may have only been created as a session object. Finally it may have been removed.
Note that RSA private keys commonly do contain the public exponent, so you can still construct a public key from just the private key object (using the modulus and public exponent, of course).
Remove the reference symbol in CK_ATTRIBUTE when setting a pointer to a CK_BYTE array - in your case modulus.
CK_ATTRIBUTE publicKeyTemplate[] = {
{CKA_TOKEN, &yes, sizeof(true)},
{CKA_WRAP, &yes, sizeof(true)},
{CKA_ENCRYPT, &yes, sizeof(true)},
{CKA_MODULUS_BITS, &modulusBits, sizeof(modulusBits)},
{CKA_MODULUS, modulus, sizeof(modulus)},
{CKA_PUBLIC_EXPONENT, &publicExponent, sizeof(publicExponent)}
I haven't tested your code, but I am able to successfully obtain modulus of an CK_OBJECT_HANDLE (private key / public key) by setting following template and making a call to C_GetAttributeValue:
CK_BYTE modulus[128];
CK_ATTRIBUTE Modulus = { CKA_MODULUS, modulus, sizeof(modulus) };
if ((rv = (*p11FunctionList->C_GetAttributeValue)(hSession, hPrivKey /*hPubKey*/, &Modulus, 1)) == CKR_OK)
{
// do something with obtained modulus
}
The generated private-public key pair was generated as follow:
CK_OBJECT_HANDLE hPrivKey, hPubKey;
CK_BBOOL bTrue = TRUE;
CK_ULONG mod_bits = 1024;
CK_MECHANISM GenMechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
CK_ATTRIBUTE GenPubTemplate[] = {
{ CKA_MODULUS_BITS, &mod_bits, sizeof(CK_ULONG) },
{ CKA_PUBLIC_EXPONENT, "\x01\x00\x01", 3 },
{ CKA_TOKEN, &bTrue, sizeof(CK_BBOOL) },
{ CKA_ID, (CK_CHAR_PTR)szKeyID, strlen(szKeyID) } }; // szKeyID is a const char *
CK_ATTRIBUTE GenPrivTemplate[] = {
{ CKA_TOKEN, &bTrue, sizeof(CK_BBOOL) },
{ CKA_PRIVATE, &bTrue, sizeof(CK_BBOOL) },
{ CKA_SENSITIVE, &bTrue, sizeof(CK_BBOOL) },
{ CKA_ID, (CK_CHAR_PTR)szKeyID, strlen(szKeyID) } }; // szKeyID is a const char *
// hSession is a CK_SESSION_HANDLE of an opened & logged in session
if ((rv = (*p11FunctionList->C_GenerateKeyPair)(hSession, &GenMechanism, GenPubTemplate, 4, GenPrivTemplate, 4, &hPubKey, &hPrivKey)) == CKR_OK)
{
// Now get the modulus of a the private / public key as described above
}
Though this has already been answered for others who want to do this we have created a PKCS#11 based wrapper for CryptoAPI, you can find it here:
https://github.com/PeculiarVentures/pvpkcs11
With this you can access keys stored in CryptoAPI as well as certificates using the native PKCS#11 interfaces.
Related
Suppose I have two class:
class Key {
private Integer id;
private String key;
}
class Value {
private Integer id;
private Integer key_id;
private String value;
}
Now I fill the first list as follows:
List<Key> keys = new ArrayLisy<>();
keys.add(new Key(1, "Name"));
keys.add(new Key(2, "Surname"));
keys.add(new Key(3, "Address"));
And the second one:
List<Value> values = new ArrayLisy<>();
values.add(new Value(1, 1, "Mark"));
values.add(new Value(2, 3, "Fifth Avenue"));
values.add(new Value(3, 2, "Fischer"));
Can you please tell me how can I rewrite the follow code:
for (Key k : keys) {
for (Value v : values) {
if (k.getId().equals(v.getKey_Id())) {
map.put(k.getKey(), v.getValue());
break;
}
}
}
Using Lambdas?
Thank you!
‐------UPDATE-------
Yes sure it works, I forget "using Lambdas" on the first post (now I added). I would like to rewrite the two nested for cicle with Lamdas.
Here is how you would do it using streams.
stream the keylist
stream an index for indexing the value list
filter matching ids
package the key instance key and the value instance value into a SimpleEntry.
then add that to a map.
Map<String, String> results = keys.stream()
.flatMap(k -> IntStream.range(0, values.size())
.filter(i -> k.getId() == values.get(i).getKey_id())
.mapToObj(i -> new AbstractMap.SimpleEntry<>(
k.getKey(), values.get(i).getValue())))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
results.entrySet().forEach(System.out::println);
prints
Address=Fifth Avenue
Surname=Fischer
Name=Mark
Imo, your way is much clearer and easier to understand. Streams/w lambdas or method references are not always the best approach.
A hybrid approach might also be considered.
allocate a map.
iterate over the keys.
stream the values trying to find a match on key_id's and return first one found.
The value was found (isPresent) add to map.
Map<String,String> map = new HashMap<>();
for (Key k : keys) {
Optional<Value> opt = values.stream()
.filter(v -> k.getId() == v.getKey_id())
.findFirst();
if (opt.isPresent()) {
map.put(k.getKey(), opt.get().getValue());
}
}
im new with blockchain and solidity and im trying to check 2 mapping result with the same key on one address, suppose i have this code
contract EventConfirmAccess{
struct eventStruct{
string event_log_time;
string event_name;
string event_id;
uint data_nik;
}
mapping(uint => eventStruct) public dictConfirmAccess;
uint[] public arrayOfData;
function loggingAccess(
uint _nik, string memory _event_log_time,
string memory _event_name, string memory _event_id,
uint _data_nik
) public{
dictConfirmAccess[_nik] = eventStruct(
{
event_log_time : _event_log_time,
event_name : _event_name,
event_id : _event_id,
data_nik : _data_nik
}
);
arrayOfData.push(_nik);
}
function checkData(uint _nik) view public returns(
string memory ,string memory,
string memory ,uint
){
return (
dictConfirmAccess[_nik].event_log_time,
dictConfirmAccess[_nik].event_name,
dictConfirmAccess[_nik].event_id,
dictConfirmAccess[_nik].data_nik
);
}
}
supposed I insert 1st data to blockchain :
loggingAccess(10001, "2020-10-11 08:10:00", "CONFIRM_1", "C_1", 10001)
after that I insert 2nd data :
loggingAccess(10001, "2020-10-11 08:20:00", "CONFIRM_2", "C_2", 10002)
when I check the array with checkData function I get result like this :
Result {
'0': '2020-10-11 08:20:00',
'1': 'CONFIRM_2',
'2': 'C_2',
'3': BN {
negative: 0,
words: [ 51784655, 4, <1 empty item> ],
length: 2,
red: null
}
}
the question is where is the result of 1st array ? how to retrieve it from blockchain? is this removed from blockchain (as far as i know blockchain data recorded forever ) ?
thankyou for you help and answer :)
Since you're storing to the mapping under the same key (dictConfirmAccess[_nik] = ...), the value gets overwritten.
Using the Remix VM emulator, it's currently not possible to access the previous states.
If this situation happened on a live network, you could connect to an archive node and retrieve the historical value using the combination of
the storage slot number
determinable, based on the property order in the contract and the mapping key - source
and the block number
for which you want to get the value
For example using the web3 getStorageAt method
const historicalValue = await web3.eth.getStorageAt(
contractAddress,
storageSlotNumber,
blockNumber
);
Note that the historical values are accessible only using off-chain tools and are not accessible from the contract itself (or other contracts).
i want to develop an IOTA application, but not a messaging application or coin based system. I want an simple example of how to store data in IOTA. For example i want to build an SCM or even an simple login/registration app. Can anyone guide me? Any sample application? i try to run https://github.com/domschiener/leaderboard-example But getting same error like https://github.com/domschiener/leaderboard-example/issues/6 How to run this.
Storing text data on the tangle is not that difficult. The following are snippets from my tangle-based app. I used IOTA's API Java wrapper library Jota.
1) Connect to IOTA node. You can find a list of nodes here https://nodes.iota.works. Also you can set up your own full node and use it instead of an external one.
final String protocol = "https";
final String url = "tuna.iotasalad.org";
final String port = "14265";
IotaAPI iotaServer = new IotaAPI.Builder().protocol(protocol).host(host).port(port).build();
2) Covert your text into trytes
String trytes = TrytesConverter.toTrytes("my text");
3) Prepare and send transaction to tangle
private static final String SEED = "IHDEENZYITYVYSPKAURUZAQKGVJERUZDJMYTANNZZGPZ9GKWTEOJJ9AAMXOGZNQLSNMFDSQOTZAEETA99";//just a random one
private static final int MIN_WEIGHT_MAGNITUDE = 14;
private static final int DEPTH = 9;
private static final int TAG = "mytag"; //optional
String tangleHash = prepareTransfer(createAddress(), trytes);
public String createAddress() throws ArgumentException {
GetNewAddressResponse res = iotaServer.getNewAddress(SEED, 2, 0, false, 1, false);
return res.getAddresses().get(0);
}
public String prepareTransfer(String address_seclevel_2, String trytes) throws ArgumentException {
List<Transfer> transfers = new ArrayList<Transfer>();
transfers.add(new Transfer(address_seclevel_2, 0, trytes, TAG));
SendTransferResponse str = iotaServer.sendTransfer(SEED, 2, DEPTH, MIN_WEIGHT_MAGNITUDE, transfers, null,
null, false, false);
if(str.getSuccessfully()!=null){
//Transfer successfully!
for(Transaction tx: str.getTransactions()) {
return tx.getHash();
}
}
return "Handle error here. Something went wrong!";
}
I need to store certificates and their private key in memory.
Certificates can be in the 4 following formats : PEM, PKCS12, PKCS7, DER.
I'ill need to write them back as PEM later.
All the snippets i see are storing only the public certificate in a X509 struct.
What about the private part ??
I've found a way using X509_INFO, but i got a major problem with it :
I haven't find a way to get a X509_INFO from DER/PKCS7/PKCS12 files
For the moment i got the following code :
QList<X509_INFO*>* Certificat::stringPEMToX509_INFO(QString stringPem)
{
QList <X509_INFO*>* liste_certificats = new QList<X509_INFO*>;
STACK_OF(X509_INFO)* pile_certificats = NULL;
X509_INFO* certificat;
BIO* bio = BIO_new(BIO_s_mem());
const char* pem = stringPem.toAscii().constData();
BIO_puts(bio, pem);
//https://github.com/openssl/openssl/blob/master/crypto/pem/pem_info.c
pile_certificats = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
for (int i = 0; i < sk_X509_INFO_num(pile_certificats); i++)
{
certificat = sk_X509_INFO_value(pile_certificats, i);
liste_certificats->push_back(certificat);
}
sk_X509_INFO_pop_free(pile_certificats, X509_INFO_free);
BIO_free_all(bio);
return liste_certificats;
}
My goal would be to have the same function but for DER, PKCS12 and PKCS7.
I tried to get a X509_INFO from a DER like this :
p12 = d2i_PKCS12_bio(bio, NULL);
certificat = X509_INFO_new();
certificat->x509 = cert;
certificat->x_pkey = pkey;
But x_pkey is a X509_PKEY and pkey an EVP_PKEY...
If there is no way to store it as a single struct, would it be possible to store my certificates as X509 + a EVP_PKEY for the private key, and still output both private and public part in a PEM ?
PKCS7 is only meant for public keys. DER and PEM are simply ways of encoding a PKCS (and many other) objects. Since you want to store everything into a single structure, you would probably most benefit from PKCS12. OpenSSL provides functions to parse PKCS12 data and get both the cert and key out of it.
I'm using C++ with nss and nspr libraries on 64 bit Ubuntu Linux and am trying to convert CERTCertificate derCert to SECKEYPublicKey but SECKEY_ImportDERPublicKey keeps returning -8183:
Security library: improperly formatted DER-encoded message.
I have also tried to use SECKEY_ImportDERPublicKey with CERTCertificate derPublicKey but I got the same response.
Which function pair should be used for derCert and which for derPublicKey conversion to SECItem and back to SECKEYPublicKey or CERTCertificate?
To answer my own question...
CERTCertificate contains two member variables derCert and derPublicKey (both of type SECItem) that I was interested in.
Save/Load public key
To get the public key you can either save CERTCertificate derPublicKey value or get the same value from SECKEYPublicKey:
// cert is of type CERTCertificate
SECKEYPublicKey* publicKey = CERT_ExtractPublicKey( cert );
SECItem* derPublicKey = SECKEY_EncodeDERSubjectPublicKeyInfo( publicKey );
// put the key into string
std::string keyString( (char*)derPublicKey->data, derPublicKey->len );
To decode the public key from string you use:
SECItem derKeyItem = {
.type = siBuffer,
.data = (unsigned char*)keyString.c_str(),
.len = (unsigned int)keyString.size()
};
CERTSubjectPublicKeyInfo* pubInf = SECKEY_DecodeDERSubjectPublicKeyInfo( &derKeyItem );
SECKEYPublicKey* publicKey = SECKEY_ExtractPublicKey( pubInf );
Save/Load certificate and get public key
To save certificate you save derCert.
To load certificate and get public key:
SECItem derCertItem = {
.type = siBuffer,
.data = (unsigned char*)certStr.c_str(),
.len = (unsigned int)certStr.size()
};
CERTCertificate cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &derCertItem, nullptr, false, false);
SECKEYPublicKey* publicKey = CERT_ExtractPublicKey(cert);
Note
The above code is sample code. For production code smart pointers (unique/shared) should be used and their destructors should call the appropriate nss destroy functions.