有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java CertGetCertificateChain内存访问无效

可见性交叉过帐:https://groups.google.com/forum/#!topic/jna-users/qfkoxPwA-r8

我正在为Crypt32库中的CertGetCertificateChain方法创建一个包装器,我希望获得帮助以解决导致崩溃的“无效内存访问”问题

包装器的签名为:

boolean CertGetCertificateChain(Pointer hChainEngine, PCERT_CONTEXT pCertContext, Pointer pTime,
            Pointer hAdditionalStore, CERT_CHAIN_PARA.ByReference pChainPara, int dwFlags, Pointer pvReserved,
            PointerByReference ppChainContext);

我使用的结构是:

public static class CERT_CHAIN_PARA extends Structure {
    public int cbSize;
    public CERT_USAGE_MATCH RequestedUsage;

    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList("cbSize", "RequestedUsage");
    }


    public static class ByReference extends CERT_CHAIN_PARA implements Structure.ByReference {}
}


public static class CERT_USAGE_MATCH extends Structure {
    public int dwType;
    public CERT_ENHKEY_USAGE Usage;


    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList("dwType", "Usage");
    }


    public static class ByReference extends CERT_USAGE_MATCH implements Structure.ByReference {}
}


public static class CERT_ENHKEY_USAGE extends Structure {
    public int cUsageIdentifier;
    public LPSTR.ByReference rgpszUsageIdentifier;


    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList("cUsageIdentifier", "rgpszUsageIdentifier");
    }


    public static class ByReference extends CERT_ENHKEY_USAGE implements Structure.ByReference {}
}

Wincrypt中有这些文件的副本。h头。CERT_CHAIN_PARA具有其他成员,这些成员仅在启用标志时才处于活动状态,而我在本机代码中未启用该标志。所以,我避免在这里添加它们

呼叫代码为:

CERT_CHAIN_PARA.ByReference pChainPara = new CERT_CHAIN_PARA.ByReference();
PointerByReference p = new PointerByReference();


pChainPara.cbSize = pChainPara.size();
pChainPara.RequestedUsage.dwType = WinCrypt.USAGE_MATCH_TYPE_AND;
pChainPara.RequestedUsage.Usage.cUsageIdentifier = 0;
pChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = null;


CertGetCertificateChain(null, pCertContext, null, null, pChainPara, 0, null, p);

崩溃发生在调用CertGetCertificateChain时。我注意到,将pChainPara设置为null可以阻止它抛出内存访问异常和崩溃。但我不确定这是否是因为pChainPara结构已损坏,或者设置null会迫使它提前失败并在其他地方掩盖问题。我检查了传入的结构的大小,它们与本机代码中的大小匹配

如果我需要提供更多信息,请告诉我。一旦实现和测试,我将清理这个问题,并将证书工作流的包装器和结构提供给JNA

编辑: 我尝试在CERT_CHAIN_PARA中添加其他成员,如下所示:

    public static class CERT_CHAIN_PARA extends Structure {

        public int cbSize;
        public CERT_USAGE_MATCH RequestedUsage;

        public CERT_USAGE_MATCH RequestedIssuancePolicy;
        public int dwUrlRetrievalTimeout;
        public boolean fCheckRevocationFreshnessTime;
        public int dwRevocationFreshnessTime;
        public FILETIME pftCacheResync;
        public CERT_STRONG_SIGN_PARA.ByReference pStrongSignPara;
        public int dwStrongSignFlags;

        @Override
        protected List<String> getFieldOrder() {
            //          return Arrays.asList("cbSize", "RequestedUsage");
            return Arrays.asList("cbSize", "RequestedUsage","RequestedIssuancePolicy","dwUrlRetrievalTimeout","fCheckRevocationFreshnessTime",
                    "dwRevocationFreshnessTime","pftCacheResync","pStrongSignPara","dwStrongSignFlags");
        }

        public static class ByReference extends CERT_CHAIN_PARA implements Structure.ByReference {

        }
    }

    public static class CERT_STRONG_SIGN_SERIALIZED_INFO extends Structure {
        DWORD dwFlags;
        LPWSTR pwszCNGSignHashAlgids;
        LPWSTR pwszCNGPubKeyMinBitLengths;

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("dwFlags", "pwszCNGSignHashAlgids", "pwszCNGPubKeyMinBitLengths");
        }

        public static class ByReference extends CERT_STRONG_SIGN_SERIALIZED_INFO implements Structure.ByReference {
        }
    }

    public static class DUMMYUNIONNAME extends Union {
        Pointer pvInfo;
        CERT_STRONG_SIGN_SERIALIZED_INFO.ByReference pSerializedInfo;
        LPSTR pszOID;
    }

    public static class CERT_STRONG_SIGN_PARA extends Structure {
        public int cbSize;
        public int dwInfoChoice;

        public DUMMYUNIONNAME union;

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("cbSize", "dwInfoChoice", "union");
        }

        public static class ByReference extends CERT_STRONG_SIGN_PARA implements Structure.ByReference {
        }
    }

    public static class FILETIME extends Structure {

        public int dwLowDateTime;
        public int dwHighDateTime;

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("dwLowDateTime", "dwHighDateTime");
        }

        public static class ByReference extends FILETIME implements Structure.ByReference {
        }

        public static class ByValue extends FILETIME implements Structure.ByValue {
        }
    }
}

并且修改了调用代码以设置其余成员:

pChainPara.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0;
pChainPara.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = null;

pChainPara.dwUrlRetrievalTimeout = 0;
pChainPara.fCheckRevocationFreshnessTime = false;
pChainPara.dwRevocationFreshnessTime = 0;
pChainPara.pftCacheResync.dwHighDateTime = 0;
pChainPara.pftCacheResync.dwLowDateTime = 0;

pChainPara.pStrongSignPara = null;

但是我还是得到了上面提到的失败

编辑2:

PCERT_CONTEXT context = CryptUIDlgSelectCertificateFromStore(store, hwnd,
                "", "", 2, 0, null);

    public static class CERT_CONTEXT extends Structure {

        public int dwCertEncodingType;
        public Pointer pbCertEncoded;
        public int cbCertEncoded;
        public Pointer pCertInfo;
        public Pointer hCertStore;

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("dwCertEncodingType", "pbCertEncoded", "cbCertEncoded", "pCertInfo", "hCertStore");
        }

        public static class ByReference extends CERT_CONTEXT implements Structure.ByReference {
        }
    }

    public static class PCERT_CONTEXT extends Structure {

        public CERT_CONTEXT.ByReference certContext;

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("certContext");
        }

        public static class ByReference extends PCERT_CONTEXT implements Structure.ByReference {
        }

        public static class ByValue extends PCERT_CONTEXT implements Structure.ByValue {
        }
    }

共 (1) 个答案

  1. # 1 楼答案

    很可能需要定义CERT_CHAIN_PARA结构的其余部分,因为它的预期大小取决于编译时变量(与cbSize中可能提供的内容无关)

    Note This member can be used only if CERT_CHAIN_PARA_HAS_EXTRA_FIELDS is defined by using the #define directive before including Wincrypt.h. If this value is defined, the application must zero all unused fields.

    更新

    PCERT_CONTEXTCERT_CONTEXT *的类型定义。您的Java定义实际上将使其CERT_CONTEXT **,至少w/r/t将其作为参数传递。如果需要本机CERT_CONTEXT *,请使用Java CERT_CONTEXT作为参数类型。在结构中嵌入指针字段可以有效地为被调用方提供希望传递的值的地址,而不是真正希望传递的指针值

    通常,您应该省略<Structure>.ByReference符号,除非您定义的结构字段需要为struct *类型