Skip to content

Commit f0f1243

Browse files
refactor: eliminate remaining code duplication flagged by SonarCloud
cng_windows.go: extract ncryptSign() helper to share the two-step NCryptSignHash pattern (size query + actual sign) between signPSS() and signPKCS1v15(). Removes ~30 duplicate lines. jwtutil: add PrintTokenInfo() sharing token preview, expiry, TokenSource, and JWT claim printing across both test drivers. Removes ~15 duplicate lines from path1 and path2 main.go. All unit tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent c6ec2ae commit f0f1243

4 files changed

Lines changed: 38 additions & 74 deletions

File tree

apps/managedidentity/cng_windows.go

Lines changed: 12 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -210,38 +210,7 @@ func (s *cngSigner) signPSS(digest []byte, opts *rsa.PSSOptions) ([]byte, error)
210210
}
211211

212212
padding := bcryptPSSPaddingInfo{pszAlgId: algNameUTF16, cbSalt: saltLen}
213-
paddingFlags := uint32(ncryptPadPSSFlag)
214-
215-
var sigLen uint32
216-
ret, _, _ := procNCryptSignHash.Call(
217-
s.hKey,
218-
uintptr(unsafe.Pointer(&padding)),
219-
uintptr(unsafe.Pointer(&digest[0])),
220-
uintptr(len(digest)),
221-
0,
222-
0,
223-
uintptr(unsafe.Pointer(&sigLen)),
224-
uintptr(paddingFlags),
225-
)
226-
if ret != 0 {
227-
return nil, fmt.Errorf("NCryptSignHash PSS (size query) failed: 0x%x", ret)
228-
}
229-
230-
sig := make([]byte, sigLen)
231-
ret, _, _ = procNCryptSignHash.Call(
232-
s.hKey,
233-
uintptr(unsafe.Pointer(&padding)),
234-
uintptr(unsafe.Pointer(&digest[0])),
235-
uintptr(len(digest)),
236-
uintptr(unsafe.Pointer(&sig[0])),
237-
uintptr(sigLen),
238-
uintptr(unsafe.Pointer(&sigLen)),
239-
uintptr(paddingFlags),
240-
)
241-
if ret != 0 {
242-
return nil, fmt.Errorf("NCryptSignHash PSS failed: 0x%x", ret)
243-
}
244-
return sig[:sigLen], nil
213+
return ncryptSign(s.hKey, unsafe.Pointer(&padding), ncryptPadPSSFlag, digest, "PSS")
245214
}
246215

247216
func (s *cngSigner) signPKCS1v15(digest []byte, opts crypto.SignerOpts) ([]byte, error) {
@@ -255,13 +224,16 @@ func (s *cngSigner) signPKCS1v15(digest []byte, opts crypto.SignerOpts) ([]byte,
255224
return nil, fmt.Errorf("converting hash alg name: %w", err)
256225
}
257226
padding := bcryptPKCS1PaddingInfo{pszAlgId: algNameUTF16}
258-
paddingFlags := uint32(0x00000002) // NCRYPT_PAD_PKCS1_FLAG
227+
return ncryptSign(s.hKey, unsafe.Pointer(&padding), 0x00000002, digest, "PKCS1v15")
228+
}
259229

260-
// Get required buffer size
230+
// ncryptSign performs a two-step NCryptSignHash call (size query, then sign)
231+
// using the provided key handle, padding info pointer, padding flags, and digest.
232+
func ncryptSign(hKey uintptr, padding unsafe.Pointer, paddingFlags uint32, digest []byte, label string) ([]byte, error) {
261233
var sigLen uint32
262234
ret, _, _ := procNCryptSignHash.Call(
263-
s.hKey,
264-
uintptr(unsafe.Pointer(&padding)),
235+
hKey,
236+
uintptr(padding),
265237
uintptr(unsafe.Pointer(&digest[0])),
266238
uintptr(len(digest)),
267239
0,
@@ -270,13 +242,13 @@ func (s *cngSigner) signPKCS1v15(digest []byte, opts crypto.SignerOpts) ([]byte,
270242
uintptr(paddingFlags),
271243
)
272244
if ret != 0 {
273-
return nil, fmt.Errorf("NCryptSignHash (size query) failed: 0x%x", ret)
245+
return nil, fmt.Errorf("NCryptSignHash %s (size query) failed: 0x%x", label, ret)
274246
}
275247

276248
sig := make([]byte, sigLen)
277249
ret, _, _ = procNCryptSignHash.Call(
278-
s.hKey,
279-
uintptr(unsafe.Pointer(&padding)),
250+
hKey,
251+
uintptr(padding),
280252
uintptr(unsafe.Pointer(&digest[0])),
281253
uintptr(len(digest)),
282254
uintptr(unsafe.Pointer(&sig[0])),
@@ -285,7 +257,7 @@ func (s *cngSigner) signPKCS1v15(digest []byte, opts crypto.SignerOpts) ([]byte,
285257
uintptr(paddingFlags),
286258
)
287259
if ret != 0 {
288-
return nil, fmt.Errorf("NCryptSignHash failed: 0x%x", ret)
260+
return nil, fmt.Errorf("NCryptSignHash %s failed: 0x%x", label, ret)
289261
}
290262
return sig[:sigLen], nil
291263
}

apps/tests/devapps/mtls-pop/internal/jwtutil/jwt.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ package jwtutil
44
import (
55
"encoding/base64"
66
"encoding/json"
7+
"fmt"
78
"strings"
9+
"time"
810
)
911

1012
// DecodeClaims decodes the JWT payload and returns (token_type, cnf) claims.
@@ -35,3 +37,25 @@ func DecodeClaims(token string) (tokenType, cnf string) {
3537
}
3638
return
3739
}
40+
41+
// PrintTokenInfo prints common mTLS PoP token details: token preview, expiry,
42+
// token source, and decoded JWT claims (token_type, cnf).
43+
func PrintTokenInfo(accessToken string, expiresOn time.Time, tokenSource int) {
44+
tokenLen := len(accessToken)
45+
if tokenLen > 60 {
46+
tokenLen = 60
47+
}
48+
fmt.Printf(" Token (first 60 chars): %s...\n", accessToken[:tokenLen])
49+
fmt.Printf(" Expires: %s\n", expiresOn)
50+
fmt.Printf(" TokenSource: %v\n", tokenSource)
51+
52+
tokenType, cnf := DecodeClaims(accessToken)
53+
fmt.Printf(" token_type (JWT): %s\n", tokenType)
54+
fmt.Printf(" cnf claim (JWT): %s\n", cnf)
55+
56+
if tokenType == "mtls_pop" {
57+
fmt.Println(" ✅ Token type is mtls_pop")
58+
} else {
59+
fmt.Printf(" ⚠️ Token type is %q (expected mtls_pop)\n", tokenType)
60+
}
61+
}

apps/tests/devapps/mtls-pop/path1_confidential/main.go

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -212,22 +212,7 @@ func testHappyPath(cred confidential.Credential, certPEM, keyPEM []byte, tenantI
212212
fmt.Println(" ❌ BindingCertificate is nil — expected non-nil for mTLS PoP")
213213
}
214214

215-
tokenLen := len(result.AccessToken)
216-
if tokenLen > 60 {
217-
tokenLen = 60
218-
}
219-
fmt.Printf(" Token (first 60 chars): %s...\n", result.AccessToken[:tokenLen])
220-
fmt.Printf(" Expires: %s\n", result.ExpiresOn)
221-
fmt.Printf(" Source: %v\n", result.Metadata.TokenSource)
222-
223-
tokenType, cnf := jwtutil.DecodeClaims(result.AccessToken)
224-
fmt.Printf(" token_type (JWT): %s\n", tokenType)
225-
fmt.Printf(" cnf claim (JWT): %s\n", cnf)
226-
if tokenType == "mtls_pop" {
227-
fmt.Println(" ✅ Token type is mtls_pop")
228-
} else {
229-
fmt.Printf(" ⚠️ Token type is %q (expected mtls_pop — verify tenant has mtlsauth enabled)\n", tokenType)
230-
}
215+
jwtutil.PrintTokenInfo(result.AccessToken, result.ExpiresOn, int(result.Metadata.TokenSource))
231216

232217
// Second call — should hit cache
233218
fmt.Println("\n Acquiring again (expect cache hit)...")

apps/tests/devapps/mtls-pop/path2_managedidentity/main.go

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -84,24 +84,7 @@ func printResult(label string, result managedidentity.AuthResult) {
8484
} else {
8585
fmt.Println(" ❌ BindingCertificate is nil — expected non-nil for mTLS PoP")
8686
}
87-
88-
tokenLen := len(result.AccessToken)
89-
if tokenLen > 60 {
90-
tokenLen = 60
91-
}
92-
fmt.Printf(" Token (first 60 chars): %s...\n", result.AccessToken[:tokenLen])
93-
fmt.Printf(" Expires: %s\n", result.ExpiresOn)
94-
fmt.Printf(" TokenSource: %v\n", result.Metadata.TokenSource)
95-
96-
tokenType, cnf := jwtutil.DecodeClaims(result.AccessToken)
97-
fmt.Printf(" token_type (JWT): %s\n", tokenType)
98-
fmt.Printf(" cnf claim (JWT): %s\n", cnf)
99-
100-
if tokenType == "mtls_pop" {
101-
fmt.Println(" ✅ Token type is mtls_pop")
102-
} else {
103-
fmt.Printf(" ⚠️ Token type is %q (expected mtls_pop)\n", tokenType)
104-
}
87+
jwtutil.PrintTokenInfo(result.AccessToken, result.ExpiresOn, int(result.Metadata.TokenSource))
10588
}
10689

10790

0 commit comments

Comments
 (0)