/// <summary> /// Derive a new encrypt key from the given decrypt key value. /// </summary> /// /// <param name="keyBits"></param> /// <returns>The new encrypt key (DER-encoded public key).</returns> public static EncryptKey deriveEncryptKey(Blob keyBits) { // Decode the PKCS #8 private key. (We don't use RSAPrivateCrtKey because // the Android library doesn't have an easy way to decode into it.) DerNode parsedNode = net.named_data.jndn.encoding.der.DerNode.parse(keyBits.buf(), 0); IList pkcs8Children = parsedNode.getChildren(); IList algorithmIdChildren = net.named_data.jndn.encoding.der.DerNode.getSequence(pkcs8Children, 1) .getChildren(); String oidString = ((DerNode.DerOid)algorithmIdChildren[0]) .toVal().toString(); Blob rsaPrivateKeyDer = ((DerNode)pkcs8Children[2]).getPayload(); String RSA_ENCRYPTION_OID = "1.2.840.113549.1.1.1"; if (!oidString.equals(RSA_ENCRYPTION_OID)) { throw new DerDecodingException( "The PKCS #8 private key is not RSA_ENCRYPTION"); } // Decode the PKCS #1 RSAPrivateKey. parsedNode = net.named_data.jndn.encoding.der.DerNode.parse(rsaPrivateKeyDer.buf(), 0); IList rsaPrivateKeyChildren = parsedNode.getChildren(); Blob modulus = ((DerNode)rsaPrivateKeyChildren[1]).getPayload(); Blob publicExponent = ((DerNode)rsaPrivateKeyChildren[2]) .getPayload(); System.SecurityPublicKey publicKey = keyFactory_ .generatePublic(new RSAPublicKeySpec(new Int64(modulus .getImmutableArray()), new Int64(publicExponent .getImmutableArray()))); return(new EncryptKey(new Blob(publicKey.getEncoded(), false))); }
/// <summary> /// Populate the fields by the decoding DER data from the Content. /// </summary> /// private void decode() { DerNode parsedNode = net.named_data.jndn.encoding.der.DerNode.parse(getContent().buf()); // We need to ensure that there are: // validity (notBefore, notAfter) // subject list // public key // (optional) extension list IList rootChildren = parsedNode.getChildren(); // 1st: validity info IList validityChildren = net.named_data.jndn.encoding.der.DerNode.getSequence(rootChildren, 0) .getChildren(); notBefore_ = ((Double)((net.named_data.jndn.encoding.der.DerNode.DerGeneralizedTime)validityChildren[0]).toVal()); notAfter_ = ((Double)((net.named_data.jndn.encoding.der.DerNode.DerGeneralizedTime)validityChildren[1]).toVal()); // 2nd: subjectList IList subjectChildren = net.named_data.jndn.encoding.der.DerNode.getSequence(rootChildren, 1) .getChildren(); for (int i = 0; i < subjectChildren.Count; ++i) { net.named_data.jndn.encoding.der.DerNode.DerSequence sd = net.named_data.jndn.encoding.der.DerNode.getSequence(subjectChildren, i); IList descriptionChildren = sd.getChildren(); String oidStr = (String)((DerNode)descriptionChildren[0]) .toVal(); String value_ren = "" + ((Blob)((DerNode)descriptionChildren[1]).toVal()); addSubjectDescription(new CertificateSubjectDescription(oidStr, value_ren)); } // 3rd: public key Blob publicKeyInfo = ((DerNode)rootChildren[2]).encode(); try { key_ = new PublicKey(publicKeyInfo); } catch (UnrecognizedKeyFormatException ex) { throw new DerDecodingException(ex.Message); } if (rootChildren.Count > 3) { IList extensionChildren = net.named_data.jndn.encoding.der.DerNode.getSequence(rootChildren, 3) .getChildren(); for (int i_0 = 0; i_0 < extensionChildren.Count; ++i_0) { net.named_data.jndn.encoding.der.DerNode.DerSequence extInfo = net.named_data.jndn.encoding.der.DerNode.getSequence(extensionChildren, i_0); IList children = extInfo.getChildren(); String oidStr_1 = (String)((DerNode)children[0]).toVal(); bool isCritical = (bool)(((Boolean)((net.named_data.jndn.encoding.der.DerNode.DerBoolean)children[1]).toVal())); Blob value_2 = (Blob)((DerNode)children[2]).toVal(); addExtension(new CertificateExtension(oidStr_1, isCritical, value_2)); } } }
/// <summary> /// Load the unencrypted private key from a buffer with the PKCS #1 encoding. /// This replaces any existing private key in this object. /// </summary> /// /// <param name="encoding">The byte buffer with the private key encoding.</param> /// <param name="keyType"></param> /// <exception cref="TpmPrivateKey.Error">for errors decoding the key.</exception> public void loadPkcs1(ByteBuffer encoding, KeyType keyType) { if (keyType == null) { // Try to determine the key type. try { DerNode parsedNode = net.named_data.jndn.encoding.der.DerNode.parse(encoding); IList children = parsedNode.getChildren(); // An RsaPrivateKey has integer version 0 and 8 integers. if (children.Count == 9 && children[0] is DerNode.DerInteger && ((int)((DerNode.DerInteger)children[0]) .toVal()) == 0 && children[1] is DerNode.DerInteger && children[2] is DerNode.DerInteger && children[3] is DerNode.DerInteger && children[4] is DerNode.DerInteger && children[5] is DerNode.DerInteger && children[6] is DerNode.DerInteger && children[7] is DerNode.DerInteger && children[8] is DerNode.DerInteger) { keyType = net.named_data.jndn.security.KeyType.RSA; } else { // Assume it is an EC key. Try decoding it below. keyType = net.named_data.jndn.security.KeyType.EC; } } catch (DerDecodingException ex) { // Assume it is an EC key. Try decoding it below. keyType = net.named_data.jndn.security.KeyType.EC; } } // Java can't decode a PKCS #1 private key, so make a PKCS #8 private key // and decode that. Blob pkcs8; if (keyType == net.named_data.jndn.security.KeyType.EC) { throw new TpmPrivateKey.Error( "TODO: loadPkcs1 for EC is not implemented"); } else if (keyType == net.named_data.jndn.security.KeyType.RSA) { pkcs8 = encodePkcs8PrivateKey(encoding, new OID(RSA_ENCRYPTION_OID), new DerNode.DerNull()); } else { throw new TpmPrivateKey.Error("loadPkcs1: Unrecognized keyType: " + keyType); } loadPkcs8(pkcs8.buf(), keyType); }
/// <summary> /// Get the encoded public key for this private key. /// </summary> /// /// <returns>The public key encoding Blob.</returns> /// <exception cref="TpmPrivateKey.Error">if no private key is loaded, or errorconverting to a public key.</exception> public Blob derivePublicKey() { if (keyType_ == net.named_data.jndn.security.KeyType.EC) { throw new TpmPrivateKey.Error( "TODO: derivePublicKey for EC is not implemented"); } else if (keyType_ == net.named_data.jndn.security.KeyType.RSA) { // Decode the PKCS #1 RSAPrivateKey. (We don't use RSAPrivateCrtKey because // the Android library doesn't have an easy way to decode into it.) IList rsaPrivateKeyChildren; try { DerNode parsedNode = net.named_data.jndn.encoding.der.DerNode.parse(toPkcs1().buf(), 0); rsaPrivateKeyChildren = parsedNode.getChildren(); } catch (DerDecodingException ex) { throw new TpmPrivateKey.Error("Error parsing RSA PKCS #1 key: " + ex); } Blob modulus = ((DerNode)rsaPrivateKeyChildren[1]) .getPayload(); Blob publicExponent = ((DerNode)rsaPrivateKeyChildren[2]) .getPayload(); try { System.SecurityPublicKey publicKey = System.KeyFactory.getInstance( "RSA").generatePublic( new RSAPublicKeySpec((modulus .getImmutableArray()), ( publicExponent.getImmutableArray()))); return(new Blob(publicKey.getEncoded(), false)); } catch (Exception ex_0) { throw new TpmPrivateKey.Error("Error making RSA public key: " + ex_0); } } else { throw new TpmPrivateKey.Error( "derivePublicKey: The private key is not loaded"); } }
public void testExtension() { // Now add an extension. String name = "/hello/kitty"; int trustClass = 0; int trustLevel = 300; net.named_data.jndn.encoding.der.DerNode.DerSequence extValueRoot = new net.named_data.jndn.encoding.der.DerNode.DerSequence(); net.named_data.jndn.encoding.der.DerNode.DerOctetString extValueName = new net.named_data.jndn.encoding.der.DerNode.DerOctetString(new Blob(name).buf()); net.named_data.jndn.encoding.der.DerNode.DerInteger extValueTrustClass = new net.named_data.jndn.encoding.der.DerNode.DerInteger(trustClass); net.named_data.jndn.encoding.der.DerNode.DerInteger extValueTrustLevel = new net.named_data.jndn.encoding.der.DerNode.DerInteger(trustLevel); extValueRoot.addChild(extValueName); extValueRoot.addChild(extValueTrustClass); extValueRoot.addChild(extValueTrustLevel); Blob extValueData = extValueRoot.encode(); String oidString = "1.3.6.1.5.32.1"; bool isCritical = true; CertificateExtension certExtension = new CertificateExtension( oidString, isCritical, extValueData); toyCert.encode(); Certificate cert = new Certificate(toyCert); cert.addExtension(certExtension); cert.encode(); Blob certData = cert.getContent(); Data plainData = new Data(); plainData.setContent(certData); // The constructor Certificate(Data) calls decode(). Certificate decodedCert = new Certificate(plainData); Assert.AssertEquals("Wrong number of certificate extensions after decoding", 1, decodedCert.getExtensionList().Count); CertificateExtension decodedExtension = (CertificateExtension)decodedCert .getExtensionList()[0]; Assert.AssertEquals("Certificate extension has the wrong OID after decoding", oidString, "" + decodedExtension.getOid()); Assert.AssertEquals( "Certificate extension has the wrong isCritical value after decoding", isCritical, decodedExtension.getIsCritical()); // Decode and check the extension value. DerNode parsedExtValue = net.named_data.jndn.encoding.der.DerNode.parse(decodedExtension.getValue() .buf()); IList decodedExtValueRoot = parsedExtValue.getChildren(); Assert.AssertEquals( "Wrong number of certificate extension value items after decoding", 3, decodedExtValueRoot.Count); net.named_data.jndn.encoding.der.DerNode.DerOctetString decodedName = (net.named_data.jndn.encoding.der.DerNode.DerOctetString)decodedExtValueRoot[0]; net.named_data.jndn.encoding.der.DerNode.DerInteger decodedTrustClass = (net.named_data.jndn.encoding.der.DerNode.DerInteger)decodedExtValueRoot[1]; net.named_data.jndn.encoding.der.DerNode.DerInteger decodedTrustLevel = (net.named_data.jndn.encoding.der.DerNode.DerInteger)decodedExtValueRoot[2]; Assert.AssertEquals("Wrong extension value name after decoding", name, "" + decodedName.toVal()); Assert.AssertEquals("Wrong extension value trust class after decoding", trustClass, (int)(Int32)decodedTrustClass.toVal()); Assert.AssertEquals("Wrong extension value trust level after decoding", trustLevel, (int)(Int32)decodedTrustLevel.toVal()); }
/// <summary> /// Create a new PublicKey by decoding the keyDer. Set the key type from the /// decoding. /// </summary> /// /// <param name="keyDer">The blob of the SubjectPublicKeyInfo DER.</param> /// <exception cref="UnrecognizedKeyFormatException">if can't decode the key DER.</exception> public PublicKey(Blob keyDer) { keyDer_ = keyDer; // Get the public key OID. String oidString = null; try { DerNode parsedNode = net.named_data.jndn.encoding.der.DerNode.parse(keyDer.buf(), 0); IList rootChildren = parsedNode.getChildren(); IList algorithmIdChildren = net.named_data.jndn.encoding.der.DerNode.getSequence(rootChildren, 0) .getChildren(); oidString = "" + ((DerNode)algorithmIdChildren[0]).toVal(); } catch (DerDecodingException ex) { throw new UnrecognizedKeyFormatException( "PublicKey: Error decoding the public key: " + ex.Message); } // Verify that the we can decode. if (oidString.equals(RSA_ENCRYPTION_OID)) { keyType_ = net.named_data.jndn.security.KeyType.RSA; KeyFactory keyFactory = null; try { keyFactory = System.KeyFactory.getInstance("RSA"); } catch (Exception exception) { // Don't expect this to happen. throw new UnrecognizedKeyFormatException( "RSA is not supported: " + exception.Message); } try { keyFactory.generatePublic(new X509EncodedKeySpec(keyDer .getImmutableArray())); } catch (InvalidKeySpecException exception_0) { // Don't expect this to happen. throw new UnrecognizedKeyFormatException( "X509EncodedKeySpec is not supported for RSA: " + exception_0.Message); } } else if (oidString.equals(EC_ENCRYPTION_OID)) { keyType_ = net.named_data.jndn.security.KeyType.ECDSA; KeyFactory keyFactory_1 = null; try { keyFactory_1 = System.KeyFactory.getInstance("EC"); } catch (Exception exception_2) { // Don't expect this to happen. throw new UnrecognizedKeyFormatException( "EC is not supported: " + exception_2.Message); } try { keyFactory_1.generatePublic(new X509EncodedKeySpec(keyDer .getImmutableArray())); } catch (InvalidKeySpecException exception_3) { // Don't expect this to happen. throw new UnrecognizedKeyFormatException( "X509EncodedKeySpec is not supported for EC: " + exception_3.Message); } } else { throw new UnrecognizedKeyFormatException( "PublicKey: Unrecognized OID " + oidString); } }
/// <summary> /// Get the private key for this name; internal helper method /// </summary> /// /// <param name="keyName">The name of the key.</param> /// <param name="keyType">Set keyType[0] to the KeyType.</param> /// <returns>The java.security.PrivateKey.</returns> /// <exception cref="System.Security.SecurityException"></exception> private PrivateKey getPrivateKey(Name keyName, KeyType[] keyType) { if (!doesKeyExist(keyName, net.named_data.jndn.security.KeyClass.PRIVATE)) { throw new SecurityException( "FilePrivateKeyStorage: Private key does not exist."); } // Read the file contents. byte[] der = this.read(keyName, net.named_data.jndn.security.KeyClass.PRIVATE); // Decode the PKCS #8 DER to find the algorithm OID. String oidString = null; try { DerNode parsedNode = net.named_data.jndn.encoding.der.DerNode.parse(ILOG.J2CsMapping.NIO.ByteBuffer.wrap(der), 0); IList pkcs8Children = parsedNode.getChildren(); IList algorithmIdChildren = net.named_data.jndn.encoding.der.DerNode.getSequence(pkcs8Children, 1) .getChildren(); oidString = "" + ((DerNode.DerOid)algorithmIdChildren[0]).toVal(); } catch (DerDecodingException ex) { throw new SecurityException( "Cannot decode the PKCS #8 private key: " + ex); } PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(der); if (oidString.equals(RSA_ENCRYPTION_OID)) { keyType[0] = net.named_data.jndn.security.KeyType.RSA; try { KeyFactory kf = System.KeyFactory.getInstance("RSA"); return(kf.generatePrivate(spec)); } catch (InvalidKeySpecException e) { // Don't expect this to happen. throw new SecurityException( "FilePrivateKeyStorage: RSA is not supported: " + e.Message); } catch (Exception e_0) { // Don't expect this to happen. throw new SecurityException( "FilePrivateKeyStorage: PKCS8EncodedKeySpec is not supported for RSA: " + e_0.Message); } } else if (oidString.equals(EC_ENCRYPTION_OID)) { keyType[0] = net.named_data.jndn.security.KeyType.EC; try { KeyFactory kf_1 = System.KeyFactory.getInstance("EC"); return(kf_1.generatePrivate(spec)); } catch (InvalidKeySpecException e_2) { // Don't expect this to happen. throw new SecurityException( "FilePrivateKeyStorage: EC is not supported: " + e_2.Message); } catch (Exception e_3) { // Don't expect this to happen. throw new SecurityException( "FilePrivateKeyStorage: PKCS8EncodedKeySpec is not supported for EC: " + e_3.Message); } } else { throw new SecurityException( "FilePrivateKeyStorage.sign: Unrecognized private key OID: " + oidString); } }
/// <summary> /// Load the encrypted private key from a buffer with the PKCS #8 encoding of /// the EncryptedPrivateKeyInfo. /// This replaces any existing private key in this object. This partially /// decodes the private key to determine the key type. /// </summary> /// /// <param name="encoding">The byte buffer with the private key encoding.</param> /// <param name="password"></param> /// <exception cref="TpmPrivateKey.Error">for errors decoding or decrypting the key.</exception> public void loadEncryptedPkcs8(ByteBuffer encoding, ByteBuffer password) { // Decode the PKCS #8 EncryptedPrivateKeyInfo. // See https://tools.ietf.org/html/rfc5208. String oidString; Object parameters; Blob encryptedKey; try { DerNode parsedNode = net.named_data.jndn.encoding.der.DerNode.parse(encoding, 0); IList encryptedPkcs8Children = parsedNode.getChildren(); IList algorithmIdChildren = net.named_data.jndn.encoding.der.DerNode.getSequence( encryptedPkcs8Children, 0).getChildren(); oidString = "" + ((DerNode.DerOid)algorithmIdChildren[0]).toVal(); parameters = algorithmIdChildren[1]; encryptedKey = (Blob)((DerNode.DerOctetString)encryptedPkcs8Children[1]).toVal(); } catch (Exception ex) { throw new TpmPrivateKey.Error( "Cannot decode the PKCS #8 EncryptedPrivateKeyInfo: " + ex); } // Use the password to get the unencrypted pkcs8Encoding. byte[] pkcs8Encoding; if (oidString.equals(PBES2_OID)) { // Decode the PBES2 parameters. See https://www.ietf.org/rfc/rfc2898.txt . String keyDerivationOidString; Object keyDerivationParameters; String encryptionSchemeOidString; Object encryptionSchemeParameters; try { IList parametersChildren = ((DerNode.DerSequence)parameters) .getChildren(); IList keyDerivationAlgorithmIdChildren = net.named_data.jndn.encoding.der.DerNode.getSequence( parametersChildren, 0).getChildren(); keyDerivationOidString = "" + ((DerNode.DerOid)keyDerivationAlgorithmIdChildren[0]).toVal(); keyDerivationParameters = keyDerivationAlgorithmIdChildren[1]; IList encryptionSchemeAlgorithmIdChildren = net.named_data.jndn.encoding.der.DerNode.getSequence( parametersChildren, 1).getChildren(); encryptionSchemeOidString = "" + ((DerNode.DerOid)encryptionSchemeAlgorithmIdChildren[0]).toVal(); encryptionSchemeParameters = encryptionSchemeAlgorithmIdChildren[1]; } catch (Exception ex_0) { throw new TpmPrivateKey.Error( "Cannot decode the PBES2 parameters: " + ex_0); } // Get the derived key from the password. byte[] derivedKey = null; if (keyDerivationOidString.equals(PBKDF2_OID)) { // Decode the PBKDF2 parameters. Blob salt; int nIterations; try { IList pbkdf2ParametersChildren = ((DerNode.DerSequence)keyDerivationParameters) .getChildren(); salt = (Blob)((DerNode.DerOctetString)pbkdf2ParametersChildren[0]).toVal(); nIterations = (int)((DerNode.DerInteger)pbkdf2ParametersChildren[1]).toVal(); } catch (Exception ex_1) { throw new TpmPrivateKey.Error( "Cannot decode the PBES2 parameters: " + ex_1); } // Check the encryption scheme here to get the needed result length. int resultLength; if (encryptionSchemeOidString.equals(DES_EDE3_CBC_OID)) { resultLength = DES_EDE3_KEY_LENGTH; } else { throw new TpmPrivateKey.Error( "Unrecognized PBES2 encryption scheme OID: " + encryptionSchemeOidString); } try { derivedKey = net.named_data.jndn.util.Common.computePbkdf2WithHmacSha1(new Blob( password, false).getImmutableArray(), salt .getImmutableArray(), nIterations, resultLength); } catch (Exception ex_2) { throw new TpmPrivateKey.Error( "Error computing the derived key using PBKDF2 with HMAC SHA1: " + ex_2); } } else { throw new TpmPrivateKey.Error( "Unrecognized PBES2 key derivation OID: " + keyDerivationOidString); } // Use the derived key to get the unencrypted pkcs8Encoding. if (encryptionSchemeOidString.equals(DES_EDE3_CBC_OID)) { // Decode the DES-EDE3-CBC parameters. Blob initialVector; try { initialVector = (Blob)((DerNode.DerOctetString)encryptionSchemeParameters) .toVal(); } catch (Exception ex_3) { throw new TpmPrivateKey.Error( "Cannot decode the DES-EDE3-CBC parameters: " + ex_3); } try { Cipher cipher = javax.crypto.Cipher .getInstance("DESede/CBC/PKCS5Padding"); cipher.init(javax.crypto.Cipher.DECRYPT_MODE, new SecretKeySpec( derivedKey, "DESede"), new IvParameterSpec( initialVector.getImmutableArray())); pkcs8Encoding = cipher.doFinal(encryptedKey .getImmutableArray()); } catch (Exception ex_4) { throw new TpmPrivateKey.Error( "Error decrypting PKCS #8 key with DES-EDE3-CBC: " + ex_4); } } else { throw new TpmPrivateKey.Error( "Unrecognized PBES2 encryption scheme OID: " + encryptionSchemeOidString); } } else { throw new TpmPrivateKey.Error( "Unrecognized PKCS #8 EncryptedPrivateKeyInfo OID: " + oidString); } loadPkcs8(ILOG.J2CsMapping.NIO.ByteBuffer.wrap(pkcs8Encoding)); }
/// <summary> /// Load the unencrypted private key from a buffer with the PKCS #8 encoding. /// This replaces any existing private key in this object. /// </summary> /// /// <param name="encoding">The byte buffer with the private key encoding.</param> /// <param name="keyType"></param> /// <exception cref="TpmPrivateKey.Error">for errors decoding the key.</exception> public void loadPkcs8(ByteBuffer encoding, KeyType keyType) { if (keyType == null) { // Decode the PKCS #8 DER to find the algorithm OID. String oidString = null; try { DerNode parsedNode = net.named_data.jndn.encoding.der.DerNode.parse(encoding, 0); IList pkcs8Children = parsedNode.getChildren(); IList algorithmIdChildren = net.named_data.jndn.encoding.der.DerNode .getSequence(pkcs8Children, 1).getChildren(); oidString = "" + ((DerNode.DerOid)algorithmIdChildren[0]).toVal(); } catch (DerDecodingException ex) { throw new TpmPrivateKey.Error( "Cannot decode the PKCS #8 private key: " + ex); } if (oidString.equals(EC_ENCRYPTION_OID)) { keyType = net.named_data.jndn.security.KeyType.EC; } else if (oidString.equals(RSA_ENCRYPTION_OID)) { keyType = net.named_data.jndn.security.KeyType.RSA; } else { throw new TpmPrivateKey.Error( "loadPkcs8: Unrecognized private key OID: " + oidString); } } // Use a Blob to get the byte array. PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(new Blob(encoding, false).getImmutableArray()); if (keyType == net.named_data.jndn.security.KeyType.EC) { try { KeyFactory kf = System.KeyFactory.getInstance("EC"); privateKey_ = kf.generatePrivate(spec); keyType_ = net.named_data.jndn.security.KeyType.EC; } catch (InvalidKeySpecException ex_0) { // Don't expect this to happen. throw new TpmPrivateKey.Error( "loadPkcs8: EC is not supported: " + ex_0); } catch (Exception ex_1) { // Don't expect this to happen. throw new TpmPrivateKey.Error( "loadPkcs8: PKCS8EncodedKeySpec is not supported for EC: " + ex_1); } } else if (keyType == net.named_data.jndn.security.KeyType.RSA) { try { KeyFactory kf_2 = System.KeyFactory.getInstance("RSA"); privateKey_ = kf_2.generatePrivate(spec); keyType_ = net.named_data.jndn.security.KeyType.RSA; } catch (InvalidKeySpecException ex_3) { // Don't expect this to happen. throw new TpmPrivateKey.Error( "loadPkcs8: RSA is not supported: " + ex_3); } catch (Exception ex_4) { // Don't expect this to happen. throw new TpmPrivateKey.Error( "loadPkcs8: PKCS8EncodedKeySpec is not supported for RSA: " + ex_4); } } else { throw new TpmPrivateKey.Error("loadPkcs8: Unrecognized keyType: " + keyType); } }