• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

H0llyW00dzZ / fiber2fa / #4

12 Jun 2024 11:32AM UTC coverage: 85.819% (+0.1%) from 85.714%
#4

push

web-flow
Improve Performance for HOTP OCRA (#196)

* Refactor OCRA Verify

- [+] refactor(otpverifier): simplify OCRA token comparison logic

* Reduce allocations per operation

- [+] refactor(benchmark_test.go): update benchmark results for OCRAVerify with reduced allocations per operation
- [+] refactor(hotp_ocra.go): optimize generateOCRA by preallocating data slice and using copy instead of append
- [+] refactor(hotp_ocra.go): simplify HOTP string formatting using fmt.Sprintf with width and padding options

6 of 6 new or added lines in 1 file covered. (100.0%)

14 existing lines in 3 files now uncovered.

1174 of 1368 relevant lines covered (85.82%)

65.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.33
/internal/otpverifier/qrcode_builder.go
1
// Copyright (c) 2024 H0llyW00dz All rights reserved.
2
//
3
// License: BSD 3-Clause License
4

5
package otpverifier
6

7
import (
8
        "image"
9
        "os"
10
        "path/filepath"
11
)
12

13
// BuildQRCode generates a QR code image for the OTP configuration.
14
func (v *TOTPVerifier) BuildQRCode(issuer, accountName string, config QRCodeConfig) ([]byte, error) {
7✔
15
        // Check if issuer or account name is empty
7✔
16
        if issuer == "" {
8✔
17
                panic("BuildQRCode: issuer cannot be empty")
1✔
18
        }
19

20
        if accountName == "" {
7✔
21
                panic("BuildQRCode: account name cannot be empty")
1✔
22
        }
23

24
        if v.config.Digits > 8 {
6✔
25
                panic("BuildQRCode: maximum digits are 8 for TOTP")
1✔
26
        }
27

28
        // Ensure the configuration has default values where needed
29
        config = ensureDefaultConfig(config)
4✔
30

4✔
31
        otpURL := v.GenerateOTPURL(issuer, accountName)
4✔
32
        qrCodeImage, err := config.GenerateQRCodeImage(otpURL)
4✔
33

4✔
34
        if err != nil {
4✔
35
                return nil, err
×
UNCOV
36
        }
×
37

38
        return config.encodeImageToPNGBytes(qrCodeImage.(*image.RGBA))
4✔
39
}
40

41
// SaveQRCodeImage saves the QR code image to a file.
42
func (v *TOTPVerifier) SaveQRCodeImage(issuer, accountName, filename string, config QRCodeConfig) error {
2✔
43
        qrCodeBytes, err := v.BuildQRCode(issuer, accountName, config)
2✔
44
        if err != nil {
2✔
45
                return err
×
UNCOV
46
        }
×
47

48
        // Use the file path from the QRCodeConfig if provided, otherwise use the current directory
49
        //
50
        // Note: There is no explicit (e.g., strict permission) requirement for the file path,
51
        // so it basically depends on the use case and any specific permission requirements.
52
        // Also, keep in mind that if running on Windows, long file paths are not allowed by default.
53
        filePath := config.FilePath
2✔
54
        if filePath == "" {
3✔
55
                filePath = "."
1✔
56
        }
1✔
57

58
        // Create the full file path by joining the file path and filename
59
        fullPath := filepath.Join(filePath, filename)
2✔
60

2✔
61
        file, err := os.Create(fullPath)
2✔
62
        if err != nil {
2✔
UNCOV
63
                return err
×
UNCOV
64
        }
×
65
        defer file.Close()
2✔
66

2✔
67
        _, err = file.Write(qrCodeBytes)
2✔
68
        return err
2✔
69
}
70

71
// SaveQRCodeImage saves the QR code image to a file.
72
func (v *HOTPVerifier) SaveQRCodeImage(issuer, accountName, filename string, config QRCodeConfig) error {
2✔
73
        qrCodeBytes, err := v.BuildQRCode(issuer, accountName, config)
2✔
74
        if err != nil {
2✔
UNCOV
75
                return err
×
UNCOV
76
        }
×
77

78
        // Use the file path from the QRCodeConfig if provided, otherwise use the current directory
79
        //
80
        // Note: There is no explicit (e.g., strict permission) requirement for the file path,
81
        // so it basically depends on the use case and any specific permission requirements.
82
        // Also, keep in mind that if running on Windows, long file paths are not allowed by default.
83
        filePath := config.FilePath
2✔
84
        if filePath == "" {
3✔
85
                filePath = "."
1✔
86
        }
1✔
87

88
        // Create the full file path by joining the file path and filename
89
        fullPath := filepath.Join(filePath, filename)
2✔
90

2✔
91
        file, err := os.Create(fullPath)
2✔
92
        if err != nil {
2✔
UNCOV
93
                return err
×
UNCOV
94
        }
×
95
        defer file.Close()
2✔
96

2✔
97
        _, err = file.Write(qrCodeBytes)
2✔
98
        return err
2✔
99
}
100

101
// BuildQRCode generates a QR code image for the OTP configuration.
102
func (v *HOTPVerifier) BuildQRCode(issuer, accountName string, config QRCodeConfig) ([]byte, error) {
7✔
103
        // Check if issuer or account name is empty
7✔
104
        if issuer == "" {
8✔
105
                panic("BuildQRCode: issuer cannot be empty")
1✔
106
        }
107

108
        if accountName == "" {
7✔
109
                panic("BuildQRCode: account name cannot be empty")
1✔
110
        }
111

112
        if v.config.Digits > 8 {
6✔
113
                panic("BuildQRCode: maximum digits are 8 for HOTP")
1✔
114
        }
115

116
        // Ensure the configuration has default values where needed
117
        config = ensureDefaultConfig(config)
4✔
118

4✔
119
        otpURL := v.GenerateOTPURL(issuer, accountName)
4✔
120
        qrCodeImage, err := config.GenerateQRCodeImage(otpURL)
4✔
121

4✔
122
        if err != nil {
4✔
UNCOV
123
                return nil, err
×
UNCOV
124
        }
×
125

126
        return config.encodeImageToPNGBytes(qrCodeImage.(*image.RGBA))
4✔
127
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc