1

Java でオープン ソースの iOS モバイル デバイス管理モジュールを作成中です。このために、[1] で Apple が提供する Ruby コードを参照しています。私はこれを設定しましたが、私にとってはうまく機能します。次に、このコードを Java に変換する必要があります。これまでのところ、PKIOperation までそれを行うことができました。PKI操作で、「SCEPサーバーが無効な応答を返しました」というメッセージが表示されます。これは、PKI操作時にデバイスに送信した誤った応答が原因であると考えられます。

ただし、インターネットで検索すると、サーバーをApache Tomcatとして使用しているため、これは「maxHttpHeaderSize」と関係があることがわかります。私はそれを増やしますが、それでも解決されません。

変換する必要があるコードは次のとおりです-Appleが提供するRubyスクリプトから取得

   if query['operation'] == "PKIOperation"
    p7sign = OpenSSL::PKCS7::PKCS7.new(req.body)
    store = OpenSSL::X509::Store.new
    p7sign.verify(nil, store, nil, OpenSSL::PKCS7::NOVERIFY)
    signers = p7sign.signers
    p7enc = OpenSSL::PKCS7::PKCS7.new(p7sign.data)
    csr = p7enc.decrypt(@@ra_key, @@ra_cert)
    cert = issueCert(csr, 1)
    degenerate_pkcs7 = OpenSSL::PKCS7::PKCS7.new()
    degenerate_pkcs7.type="signed"
    degenerate_pkcs7.certificates=[cert]
    enc_cert = OpenSSL::PKCS7.encrypt(p7sign.certificates, degenerate_pkcs7.to_der, 
        OpenSSL::Cipher::Cipher::new("des-ede3-cbc"), OpenSSL::PKCS7::BINARY)
    reply = OpenSSL::PKCS7.sign(@@ra_cert, @@ra_key, enc_cert.to_der, [], OpenSSL::PKCS7::BINARY)
    res['Content-Type'] = "application/x-pki-message"
    res.body = reply.to_der
   end

これが、Bouncycastle ライブラリを使用して Java で作成した方法です。

        X509Certificate generatedCertificate = generateCertificateFromCSR(
                privateKeyCA, certRequest, certCA.getIssuerX500Principal()
                        .getName());

        CMSTypedData msg = new CMSProcessableByteArray(
                generatedCertificate.getEncoded());
        CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
        edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(
                receivedCert).setProvider(AppConfigurations.PROVIDER));
        CMSEnvelopedData envelopedData = edGen
                .generate(
                        msg,
                        new JceCMSContentEncryptorBuilder(
                                CMSAlgorithm.DES_EDE3_CBC).setProvider(
                                AppConfigurations.PROVIDER).build());

        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
        ContentSigner sha1Signer = new JcaContentSignerBuilder(
                AppConfigurations.SIGNATUREALGO).setProvider(
                AppConfigurations.PROVIDER).build(privateKeyRA);

        List<X509Certificate> certList = new ArrayList<X509Certificate>();
        CMSTypedData cmsByteArray = new CMSProcessableByteArray(
                envelopedData.getEncoded());
        certList.add(certRA);

        Store certs = new JcaCertStore(certList);

        gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(
                new JcaDigestCalculatorProviderBuilder().setProvider(
                        AppConfigurations.PROVIDER).build()).build(
                sha1Signer, certRA));

        gen.addCertificates(certs);

        CMSSignedData sigData = gen.generate(cmsByteArray, true);

        return sigData.getEncoded();

ここで返された結果は、コンテンツ タイプ「application/x-pki-message」のサーブレット出力ストリームに出力されます。

CSRを適切に取得しているようで、次のコードを使用してX509Certificateを生成します。

    public static X509Certificate generateCertificateFromCSR(
        PrivateKey privateKey, PKCS10CertificationRequest request,
        String issueSubject) throws Exception {

    Calendar targetDate1 = Calendar.getInstance();
    targetDate1.setTime(new Date());
    targetDate1.add(Calendar.DAY_OF_MONTH, -1);

    Calendar targetDate2 = Calendar.getInstance();
    targetDate2.setTime(new Date());
    targetDate2.add(Calendar.YEAR, 2);

    // yesterday
    Date validityBeginDate = targetDate1.getTime();
    // in 2 years
    Date validityEndDate = targetDate2.getTime();

    X509v3CertificateBuilder certGen = new X509v3CertificateBuilder(
            new X500Name(issueSubject), BigInteger.valueOf(System
                    .currentTimeMillis()), validityBeginDate,
            validityEndDate, request.getSubject(),
            request.getSubjectPublicKeyInfo());
    certGen.addExtension(X509Extension.keyUsage, true, new KeyUsage(
            KeyUsage.digitalSignature | KeyUsage.keyEncipherment));

    ContentSigner sigGen = new JcaContentSignerBuilder(
            AppConfigurations.SHA256_RSA).setProvider(
            AppConfigurations.PROVIDER).build(privateKey);

    X509Certificate issuedCert = new JcaX509CertificateConverter()
            .setProvider(AppConfigurations.PROVIDER).getCertificate(
                    certGen.build(sigGen));

    return issuedCert;
}

生成された証明書の共通名は、

一般名: mdm(88094024-2372-4c9f-9c87-fa814011c525)

発行者: mycompany ルート CA (93a7d1a0-130b-42b8-bbd6-728f7c1837cf)、なし

[1] - https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/iPhoneOTAConfiguration/Introduction/Introduction.html

4

1 に答える 1

2

いくつかの考え(本当の答えではありません)

1) 「SCEP サーバーが無効な応答を返しました」は、さまざまな理由で返される可能性があります。一般的に言えば、SCEP が MDM クライアントによって解析できないものを返す場合、このエラーが表示されます。

2) jSCEP ( https://code.google.com/p/jscep/ ) をご覧ください。これは、SCEP サーバーの Java 実装です。そして、私はそれがiOSで動作することを確信しています(私はそれを使用しました)。

  • 両方がどのように処理しているかを確認できます (私が覚えているように、彼らも Bouncy Castle を使用しています)。

  • また、サイクルを再発明するよりも、オープン ソースの実装に jSCEP を含めたいと思います。SCEP RFC には非常に多くの部分があり、jSCEP はそれに従うのが得意です。

于 2013-09-14T14:41:52.907 に答える