Using Windows 7, JDK 6 (and 7).
I'm trying to get personal certificates stored in Windows MSCAPI key store and it's basic properties (in order to use private key for signing). However some aliases are identified not having private key (isKeyEntry == false) although it acctually has one.
Any suggestions how to deal with this "feature"?
The P12 file with certificate (already revoked) & private key having this weird "property" can be downloaded from http://download.upce.cz/terena-public.pfx. Password is "password".
KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
ks.load(null, null);
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements()) {
String alias = (String) aliases.nextElement();
X509CertImpl certificate = (X509CertImpl)ks.getCertificate(alias);
System.out.println("Alias: " + alias);
System.out.println(" Subject: " + certificate.getSubjectDN());
System.out.println(" Issued By: " + certificate.getIssuerDN());
if (ks.isKeyEntry(alias)) {
System.out.println(" Has private key");
}
}
I imported your pfx-file into Mozilla Thunderbird and exported it as p12-file. Now I can see it through MSCAPI. There must be something in the original certificate that prevents MSCAPI to see the private key.
I compared the files and I noticed that in the original file the Key Usage section is used.
Original pfx:
Bag Attributes
localKeyID: 01 00 00 00
friendlyName: le-b6311e84-87e7-4e02-9cf6-4012518e0541
Microsoft CSP Name: Microsoft Software Key Storage Provider
Key Attributes
X509v3 Key Usage: 90
Converted p12:
Bag Attributes
friendlyName: le-b6311e84-87e7-4e02-9cf6-4012518e0541
localKeyID: 47 E4 D3 F0 75 48 9D 77 07 E9 51 A4 F1 B6 DF E9 40 80 26 7A
Key Attributes: <No Attributes>
There are more differences in the two files, but I'm not sure which one causes the unwanted behaviour.
Related
RFC 8410 lists this as an example of a Ed25519 public key: MCowBQYDK2VwAyEAGb9ECWmEzf6FQbrBZ9w7lshQhqowtrbLDFw4rXAxZuE=
Decoding this with an ASN.1 decoder, this becomes:
30 2A
30 05
06 03 2B6570 // Algorithm Identifier
03 21 0019BF44096984CDFE8541BAC167DC3B96C85086AA30B6B6CB0C5C38AD703166E1
As expected, this matches the SubjectPublicKeyInfo definition in the RFC.
Using the Sun cryptography provider in Java 11+ I can use this code to generate an X25519 (not Ed25519 - which is the difference in the algorithm identifier below) public key:
import java.security.KeyPairGenerator;
import java.util.Base64;
public class PrintPublicKey {
public static void main(String args[]) throws Exception {
KeyPairGenerator generator = KeyPairGenerator.getInstance("X25519");
byte[] encodedPublicKey = generator.generateKeyPair().getPublic().getEncoded();
System.out.println(Base64.getEncoder().encodeToString(encodedPublicKey));
}
}
Which will output something like: MCwwBwYDK2VuBQADIQDlXKI/cMoICnQRrV+4c//viHnXMoB190/z2MX/otJQQw==
Decoding this with an ASN.1 decoder, this becomes:
30 2C
30 07
06 03 2B656E // Algorithm Identifier
05 00 // Algorithm Parameters - NULL
03 21 00E55CA23F70CA080A7411AD5FB873FFEF8879D7328075F74FF3D8C5FFA2D25043
This has an explicit NULL after the object identifier. Is this valid according to the specification? It says:
In this document, we define four new OIDs for identifying the different curve/algorithm pairs: the curves being curve25519 and curve448 and the algorithms being ECDH and EdDSA in pure mode.
For all of the OIDs, the parameters MUST be absent.
The paragraph after the one you quoted says this:
It is possible to find systems that require the parameters to be
present. This can be due to either a defect in the original 1997
syntax or a programming error where developers never got input where
this was not true. The optimal solution is to fix these systems;
where this is not possible, the problem needs to be restricted to
that subsystem and not propagated to the Internet.
So a plausible explanation for the Oracle implementation's behavior is that they want to be interoperable with old systems that require parameters. It is the kind of thing that you do to prevent big customers with large support contracts from complaining loudly that "upgrading to Java 11 broke my infrastructure".
I would like to read the extension BasicConstraints from Java X509Certificate (the certificate implementation comes from default JCE so it is sun.security.x509.X509CertImpl).
I wanted to get the BasicConstraint extension value to check if it is CA :
X509Certificate certificate = ...
byte[] basicConstraint = certificate.getExtensionValue("2.5.29.19");
But this gives me byte array that contains DEROctetString. And after unwrapping it I get byte array with 2 bytes.
However the extension BasicConstraint seems to be defined as :
BasicConstraints := SEQUENCE {
cA BOOLEAN DEFAULT FALSE,
pathLenConstraint INTEGER (0..MAX) OPTIONAL
}
I have already looked at X509Certificate::getBasicConstraints() method which returns an int. The problem is that it also returns -1 when the extension is not present.
That is why I am looking for a way to get this ASN1 sequence from X509 certificate to explicitly check this CA boolean flag.
The valid encodings of the BasicConstraints extension (within the OCTET STRING) are:
CA=false: 30 00
CA=true, pathlen omitted: 30 03 01 01 FF
CA=true, pathlen=0 to 127: 30 06 01 01 FF 02 01 xx
CA=true, pathlen >= 128: using such long paths is so silly I omit this case, but you can work it out using the DER rules if you really want
You most likely have case 1.
So I am trying to read my transportation card using what I have learned so far about smartcards.
My ATR is: 3B 6F 00 00 80 5A 0A 07 06 20 04 01 03 01 F4 1F 82 90 00
when I looked in the ATR parser it didn't give me much information.
when I chose the MF file like this: "00 A4 04 00"
I got the response: "90 00"
output: but no data.
How can I go on from here to read files on my card?
Note: [it would be nice if someone can give me a link to a book or guide about smart cards, cause I found nice one about EMV cards but it is not working on all smartcards]
https://www.eftlab.com/knowledge-base/171-atr-list-full/ shows that from your atr, there are similar cards with similar ATR data.
You can try selecting the dedicated file using the offsets below and see what happens;
0x0002
0x0003
0x2000
0x2001
0x2004
0x2010
0x2020
0x202a
0x202b
0x202c
0x202d
0x2030
0x2040
0x2050
0x2069
0x206a
0x20f0
0x2100
0x2101
0x2104
0x2110
0x2120
0x2140
0x2150
0x2169
0x21f0
0x2f10
0x3f04
0xfeff
hope you can continue from there.
Select first the MF by performing CLA INS P1 P2 Lc DATA
EX.
CLA 00
INS A4
P1 04 - to select by Name
P2 00 - Select first or only occurrence
Lc - Length of FID
Data - FID
I want to get a specific record from a set in aerospike.
But when i execute the following query, i got no result:
select * from ctl.prodCache where PK='111222';
But when i execute the following query:
select * from ctl.prodCache;
It gives me all the records, but does not shows the primary key at all.
{
"edigest": "BE6ZxLRMKwnbmUqPTvsmcIAgVv8=",
"set": "prodCache",
"ttl": 54,
"gen": 1,
"bins": {
"C": "java.util.ArrayList",
"V": "00 10 70 61 79 74 6D 6D 61 2E 64 6F 6D 61 69 6E 2E 43 "
}
}
Any suggestions? Please help.
By default, Aerospike does not store your primary key. It stores a RIPEMD160 hash of your key+ 1 byte for key type + set name. This is what you are seeing in base64 in the digest output. In AQL, you can set SEND_KEY true, and then it will show in the metadata about the record. In AQL do SET RECORD_PRINT_METADATA true and SET OUTPUT JSON for better visibility. Now, your query with PK='111222' it should work if your key was a string '111222', if it was an integer, use PK=111222 and that should work.
That's because the default is not to store the primary key with the record. A record is identified by the tuple (namespace, set, PK), and is then hashed by the client through RIPEMD-160 into a 20 byte digest. That digest is the actual identifier of the record. It's how the client finds its partition ID, looks up which nodes has the master of that partition, and goes to that node with one hop.
On that node, the digest is what is being matched against the primary index to find this record's metadata. A scan will walk the primary index for a particular namespace, get the metadata of all the records, and stream them back to the client. If you chose to have the sendKey attribute of your write policy set to true, the key will be saved along with the record's data. Then you can get to it from the scan/query. By default this doesn't happen, because that could mean a lot of space
First execute the following commands from AQL:
SET KEY_SEND TRUE
and then insert the data in specific sets.
After that, execute the select query.
The PK will be shown only for the inserts for which the insertions were done setting the KEY_SEND to true.
I found a difference in the output to PEM file that openssl generates with different versions.
I use following command to generate the PEM file
So for the same p12 file we get following output:
From version 0.9.8
Bag Attributes
friendlyName: alias
localKeyID: 54 69 6D 65 20 31 34 34 30 31 35 39 36 39 39 34 30 38
Key Attributes: <No Attributes>
-----BEGIN DSA PRIVATE KEY-----
MIIBuwIBAAKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR
+1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb
+DtX58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdg
UI8VIwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlX
TAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCj
rh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQB
TDv+z0kqAoGAfq00gXUAZKs/5070DyJJ2OPmgTsMkRXeAclk3mlvejzaiswmM50i
NuV4EYP0SeSzxxzMNR+0U8xg8M/R7a4qMAsDiHixM8i/HGrqC5m+/Zabg3FVNVEQ
C1sFNiqeP3P6n986HrRK5WbEFcJKMZFAbFTwXeo0D6Uevi2ZzYrm0cgCFE6W9Uw2
ZHF1HYhy0L49DUQN79LL
-----END DSA PRIVATE KEY-----
Bag Attributes
friendlyName: alias
localKeyID: 54 69 6D 65 20 31 34 34 30 31 35 39 36 39 39 34 30 38
subject=/CN=HCP
issuer=/CN=HCP
-----BEGIN CERTIFICATE-----
MIICeDCCAjagAwIBAgIEHpWeZDALBgcqhkjOOAQDBQAwDjEMMAoGA1UEAxMDSENQ
MB4XDTE1MDgyMTEyMjEwOFoXDTE1MTExOTEyMjEwOFowDjEMMAoGA1UEAxMDSENQ
MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9E
AMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f
6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv
8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtc
NrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwky
jMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/h
WuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAfq00gXUAZKs/5070DyJJ2OPmgTsM
kRXeAclk3mlvejzaiswmM50iNuV4EYP0SeSzxxzMNR+0U8xg8M/R7a4qMAsDiHix
M8i/HGrqC5m+/Zabg3FVNVEQC1sFNiqeP3P6n986HrRK5WbEFcJKMZFAbFTwXeo0
D6Uevi2ZzYrm0cijITAfMB0GA1UdDgQWBBTo5c7HXDNXFjVl5cPJLHTKGqXXFTAL
BgcqhkjOOAQDBQADLwAwLAIUCI0RfR7sVsNpzMKFlCvx8G5nSZACFCkcmf5mPKoz
ytbeIPWod7vQNmEz
-----END CERTIFICATE-----
from version 1.0.1g the output is following:
Bag Attributes
friendlyName: alias
localKeyID: 54 69 6D 65 20 31 34 34 30 31 35 39 36 39 39 34 30 38
Key Attributes: <No Attributes>
-----BEGIN PRIVATE KEY-----
MIIBSwIBADCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdS
PO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVCl
pJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith
1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7L
vKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3
zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImo
g9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoEFgIUTpb1TDZkcXUdiHLQvj0NRA3v0ss=
-----END PRIVATE KEY-----
Bag Attributes
friendlyName: alias
localKeyID: 54 69 6D 65 20 31 34 34 30 31 35 39 36 39 39 34 30 38
subject=/CN=HCP
issuer=/CN=HCP
-----BEGIN CERTIFICATE-----
MIICeDCCAjagAwIBAgIEHpWeZDALBgcqhkjOOAQDBQAwDjEMMAoGA1UEAxMDSENQ
MB4XDTE1MDgyMTEyMjEwOFoXDTE1MTExOTEyMjEwOFowDjEMMAoGA1UEAxMDSENQ
MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9E
AMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f
6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv
8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtc
NrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwky
jMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/h
WuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAfq00gXUAZKs/5070DyJJ2OPmgTsM
kRXeAclk3mlvejzaiswmM50iNuV4EYP0SeSzxxzMNR+0U8xg8M/R7a4qMAsDiHix
M8i/HGrqC5m+/Zabg3FVNVEQC1sFNiqeP3P6n986HrRK5WbEFcJKMZFAbFTwXeo0
D6Uevi2ZzYrm0cijITAfMB0GA1UdDgQWBBTo5c7HXDNXFjVl5cPJLHTKGqXXFTAL
BgcqhkjOOAQDBQADLwAwLAIUCI0RfR7sVsNpzMKFlCvx8G5nSZACFCkcmf5mPKoz
ytbeIPWod7vQNmEz
-----END CERTIFICATE-----
So there is a difference in the private key.
Problem is that later we try to parse the private key from Java with following code:
KeyFactory keyFactory = KeyFactory.getInstance("DSA");
KeySpec privateKeySpec = new PKCS8EncodedKeySpec(Base64.decode(key));
keyFactory.generatePrivate(privateKeySpec);
then the output of version 0.9.8 is not parsed and fails with InvalidKeySpec.
Was something changed in OpenSSL and how can we avoid this?